Страницы

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

вторник, 15 января 2019 г.

Условная компиляция

А как в Java реализуется условная компиляция?
Скажем, у меня есть TCP сервер. Мне нужно на этапе отладки складывать в файл пришедшие пакеты. Потом, в релиз версии, этот функционал нужно будет отключить.
Как такое принято реализовывать? В Си это делается так
#ifdef DEBUG savePacket(); #endif
а в Java?


Ответ

Есть ещё один способ эмулировать макросы препроцессора - процессоры аннотаций + Java Compiler API. Этот способ сложнее, но не требует дополнительных библиотек и не выполняет никаких дополнительных действий в рантайме, все изменения в код вносятся в процессе его компиляции, между этапом разбора исходного текста и преобразования его в байткод.
Аннотация для активации отладочных действий:
package com.example;
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
@Retention(RetentionPolicy.SOURCE) // Аннотация существует только до компиляции @Target(ElementType.METHOD) public @interface Debug { // Чтобы отключать аннотацию, не убирая её // но можно и без этого boolean value() default true; }
Жертва эксперимента:
import com.example.Debug;
public class SomeServer { private void savePacket() { System.out.println("Packet saved"); }
@Debug private void receivePacket() { System.out.println("Packet received"); }
public static void main(String[] args) { SomeServer srv = new SomeServer(); srv.receivePacket(); } }
Процессор
package com.example;
import com.sun.tools.javac.model.JavacElements; import com.sun.tools.javac.processing.JavacProcessingEnvironment; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.List;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.annotation.processing.SupportedSourceVersion; import javax.annotation.processing.SupportedOptions; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic;
@SupportedOptions("debug") @SupportedAnnotationTypes("com.example.Debug") @SupportedSourceVersion(SourceVersion.RELEASE_8) public class DebugProcessor extends AbstractProcessor { @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { if (roundEnv.processingOver()) return false;
// Получаем параметр указывающий на отладочную сборку boolean enabled = Boolean.parseBoolean( processingEnv.getOptions().getOrDefault("debug", "false"));
Context ctx = ((JavacProcessingEnvironment) processingEnv).getContext(); JavacElements elementUtils = (JavacElements) processingEnv.getElementUtils(); TreeMaker treeMaker = TreeMaker.instance(ctx);
// Обходим методы помеченные аннотацией @Debug for (Element element : roundEnv.getElementsAnnotatedWith(Debug.class)) { Debug debug = element.getAnnotation(Debug.class);
if (debug.value() && enabled) { JCTree.JCMethodDecl jcMethodDecl = (JCTree.JCMethodDecl) elementUtils.getTree(element);
// И добавляем в конец метода вызов другого метода treeMaker.pos = jcMethodDecl.pos; jcMethodDecl.body = treeMaker.Block(0, List.of( jcMethodDecl.body, treeMaker.Exec( treeMaker.Apply( List.nil(), treeMaker.Select( treeMaker.Ident( elementUtils.getName("this") ), elementUtils.getName("savePacket") ), List.nil() ) ) )); } }
return false; } }
Собираем аннотацию
$ javac -d build Debug.java
Собираем процессор
$ javac -cp build:"$JAVA_HOME/lib/tools.jar" -d build DebugProcessor.java
А теперь собираем SomeServer с использованием процессора
$ javac -cp build -processor com.example.DebugProcessor -Adebug=true SomeServer.java
Или можно собрать сервисный jar и положить в classpath, чтобы процессор использовался автоматически. Для этого DebugProcessor.class надо упаковать в jar вместе с файлом META-INF/services/javax.annotation.processing.Processor содержащим строку com.example.DebugProcessor. Тогда при сборке останется только указывать параметр -Adebug=true, когда нужны отладочные действия, и просто не указывать в другом случае.
P.S. По-хорошему надо было ещё метод savePacket тоже генерировать на лету, но я несколько притомился. Может дополню ответ в другой день. P.P.S. И возможно, напишу ещё третий ответ - про написание плагинов для компилятора.

Зачем индексировать внешний / вторичный (foreign key) ключ в MySQL?

Есть понятие "ограничитель" в MySQL. Например, это первичный ключ (ключ должен быть уникален, поэтому каждый раз производится поиск "а не было ли этого ключа в предыдущих строках?" для ускорения которого автоматом столбец с первичным ключом индексируется) и ключ-кандидат (та же логика, что и с первичным ключом). То есть, есть логика: будет поиск каждый раз поиск, значит, надо проиндексировать.
Теперь возьмем вторичный ключ. Он ссылается на таблицу-список. При создании новой строки в таблице надо проверить, а есть ли в таблице-списке этот вторичный ключ. То есть, вторичный ключ ограничивает.
ВОПРОС: зачем индексировать вторичный ключ? Это же, например, столбец с номерами преподавателей (а в таблице-списке расшифровывается какой препод какому номеру соответствует). Зачем что-то искать в столбце вида "1,2,5,1,3,10..."?


Ответ

Основная причина - возможность быстрой проверки на "осиротелые вторичные ключи" (orphaned rows) в случае удаления (DELETE) или смены (UPDATE - лучше так не делать) значений первичного ключа.
Пример:
table master
id (PK) val 1 11 2 22 3 33
table slave
id (PK) master_id (FK) val 1 1 111 2 1 112 3 2 311
при удалении:
delete from master where id = 3;
СУБД должна проверить - можно ли удалить PK == 3 для этого проверяются все таблицы содержащие вторичные ключи референцирующие столбец master.id и только если значение 3 не встречается ни в одном из вторичных ключей, тогда удаление разрешается.
Также существует возможность каскадного удаления (ON DELETE CASCADE) или перезаписи соответствующих значений вторичных ключей значением NULL (ON DELETE SET NULL) - в этих случаях нам тоже нужен быстрый (индексированный) доступ ко вторичным ключам.

Активити создается с нуля при возвращении из нового активити

Есть активити MainActivity, содержащее пару фрагментов прописанных через xml. Также есть еще одно активити, запускаемое из MainActivity. При возвращении из это нового активити в основное происходит следующее: сначала вызывается метод onDestroy основного активити который также убивает все фрагменты, а затем все создается заново как при простом запуске.
Может кто ни будь объяснить мне такое поведение андроида и как тогда сохранить между такими пересоздаваниями состояния активити и фрагментов. Например Текст или изображения, заданные не через xml, а в коде или массив данных?
ЗЫ. Руководствовался этой схемой, но вроде бы они все одинаковые в интернете и на всех схемах onDestroy вызывается только при уничтожении активити
// Старт приложения MainActivity.onCreate called
PlayerFragment.onCreate called PlayerFragment.onCreateView called
PlaylistFragment.onCreate called PlaylistFragment.onCreateView called
MainActivity.onResume called
// Запуск нового активити PreferencesActivity.onCreate called
// Жмем кнопку назад MainActivity.onDestroy called // Почему это а не onResume? PlayerFragment.onDestroy called PlaylistFragment.onDestroy called
MainActivity.onCreate called PlayerFragment.onCreate called PlayerFragment.onCreateView called PlaylistFragment.onCreate called PlaylistFragment.onCreateView called
MainActivity.onResume called


Ответ

Если вы делаете переход назад onBackPressed() или finish() покажите ваш манифест. Исходя из вашего ответа вы выставили определенную стратегию в launchMode, аналогичное поведение было бы если бы у вас стояло
android:launchMode="singleInstance"
или
android:launchMode="singleTask"
после этого вы заменили на android:launchMode="singleTop" и это standart condition, те обычное поведеине со стратегией не создавать новый экземплер если он на вершине стека.
Возмоно также вы делали переход с помощью намерениея Intent, здесь тогда все становится намного сложней. Вам кажется что вы сделали переход назад, но по факту вам ещё нужно следить за PreferencesActivity она у вас ещё в стеке, вы выставили singleTop и просто не пересозадил активити с вершиной на стеке, будьте внимательны использую задачи и стек переходов, это очень важно. Вы можете, сделать серфинг по приложению - бесшовным и плавным при этом экономить проц время и объем потреблям трафика.
Здесь есть все для того чтоб понять суть
https://developer.android.com/guide/components/tasks-and-back-stack?hl=ru
удачи

Django Admin, SELECT по полям

Есть модуль UserTask в которой есть очень тяжелые поля и они тормозят запрос, как можно убрать их из запроса для Django Admin.
Они не выводятся на страницу, но Django использует примерно такой запрос:
SELECT * FROM UserTask;
А нужно:
SELECT id, name, is_user FROM UserTask;
P.S. Нужно убрать их именно в админке, вот регистрация модели:
class UserTaskAdmin(admin.ModelAdmin): list_filter = ('id', 'name') list_display = ('id', 'name')
admin.site.register(UserTask, UserTaskAdmin)
кривой перевод на английский


Ответ

Вы можете переопределить get_queryset() и использовать only() метод:
class UserTaskAdmin(admin.ModelAdmin): list_filter = ('id', 'name') list_display = ('id', 'name')
def get_queryset(self, request): return self.model.objects.only('id', 'name')
Немного изменил оригинал, там использовался UserTask.objects.only('id', 'name'), за места self.model.objects.only('id', 'name'), что ограничивало повторное использования кода с другими моделями.
Оригинал от @neverwalkaloner

Проблема с array_rand

if ($sex == 1){ $skin = array(1,2,3,4,5); // Рандомные мужские скины $model = array_rand($skin); } if ($sex == 2){ $skin = array(1,2,3,4,5); // Рандомные женские скины $model = array_rand($skin); }
Помогите, при var_dump($model) пишет NULL


Ответ

$data['sex'] = '1';
switch ($data['sex']) { case 1: $skin = array(1,2,3,4,5); $model = $skin[array_rand($skin)]; break; case 2: $skin = array(1,2,3,4,5); $model = $skin[array_rand($skin)]; break; default: break; }
var_dump($model);
http://sandbox.onlinephpfunctions.com/ - вводим сюда и жмякаем на Execute Code

js, как в строке в каждом слове сделать первую букву в верхний регистр?

как в строке в каждом слове сделать первую букву в верхний регистр ? Точнее как сделать это регуляркой ?


Ответ

let str = 'исходная Строка дЛЯ теста'; let res = str.replace(/(?:^|\s)(\S)/ug, m => m.toUpperCase()); console.log(res);
(?:^|\s) - начало строки или пробельный символ (\S) - непробельный символ с захватом для замены
Насколько я знаю, в js regexp нет аналога \b для unicode.

В некоторых случаях, эта регулярка не подойдёт(из-за отсутствия пробелов): а,б,в
Проще всего использовать класс \p{L}
let str = 'исходная Строка дЛЯ теста(раз,два,три)'; let res = str.replace(/(?:^|[^\p{L}])(\p{L})/ug, m => m.toUpperCase()); console.log(res);

Шаблон регулярного выражения для поиска полного совпадения со строкой

Нужна помощь с регулярным выражением, а точнее с составлением шаблона, для поиска полного совпадения со строкой.
Пример:
import re
word = input() with open('first.txt', 'r') as file1: line = file1.read() if re.search(word, line): #т.к.ищется первое вхождение, то нужно как - то настроить шаблон, и я не понимаю как это сделать print('слово найдено')


Ответ

Правильно ли я вас понял, с учетом строгого соответствия?
import re
word = input() with open('first.txt', 'r') as file1: for line in file1.readlines(): if re.findall('^' + word + '$', line): print('Cлово найдено') else: print('Не найдено')

Разбить массив по элементам второго массива

Есть массив типа:
abcsbbc adsdv absutd ffdbbc ffdddv auuutd ...
есть второй массив типа:
bbc ddv dv utd
так вот мне нужно разбить значения первого массива по значениям второго чтоб получилось так:
abcs_bbc ads_dv abs_utd ffd_bbc ffd_ddv auu_utd
Важно понимать что во втором массиве может быть минимум 2 буквы. Тоесть скрипт должен учитывать только те буквы которые в самом конце элементов первого массива, так как элементы второго массива всегда в конце первого.


Ответ

Уже сам нашел решение, вот:
foreach($arr1 as $x){ foreach($arr2 as $z){ if(preg_match("/$z$/", $x)){ $this->array[$x][0] = preg_replace("/$z$/", '', $x); $this->array[$x][1] = $z; } } }

Можно в IntelliJ IDEA посмотреть где используется метод?

И если можно, то как? Поиск(Ctrl+F и т.п.) не подходит.


Ответ

Для просмотра того где используется метод нужно сделать следующее:
Установить курсор на название метода который хотите проверить Нажать сочетание клавиш Ctrl + B или зажать Ctrl и нажать ЛКМ на имя метода.
После этого либо произойдет переход к месту использования или появится список мест где используется данный метод. Данная комбинация так же может работать с классами и интерфейсами.

Как сверстать такую обводку?


Пробовал так:
.text p{ position: relative; text-transform: uppercase; z-index: 1; margin-top: 30px; color: #fde428; display: inline-block; cursor: pointer; border-bottom: 2px solid #fde428; } .text{ position: relative; text-align: right; width: 50%; } .text h2{ position: relative; } .text::after{ content: ""; width: 180px; height: 220px; border: 5px solid #fde428; position: absolute; border-left: transparent; top: -20px; right: calc(50px - 180px); } .text h2::after{ content: ""; width: 5px; height: 16px; background: #fde428; position: absolute; border-left: transparent; top: -17px; right: 50px; } .text p::after{ content: ""; text-decoration: none; width: 5px; height: 16px; cursor: default; background:#fde428; position: absolute; border-left: transparent; top: -22px; right: 50%; } .text p:before{ text-decoration: none; content: ""; width: 5px; height: 54px; cursor: default; background:#fde428; position: absolute; border-left: transparent; top: 22px; right: 50%; }

Consumer
Products
Consulting

LEARN MORE


Да уж больно криво и костыльно мне кажется.


Ответ

Могу предложить такое решение на codePen.io.
body { background-color: #555; } .text{ position: relative; margin: 0 auto; text-align: right; width: 180px; height: 220px; border: 5px solid #fde428; border-left: transparent; } .text::before, .text::after { content: ""; position: absolute; left: -5px; display: block; width: 5px; } .text::before { height: 20px; box-shadow: 5px 125px 0 #fde428; } .text::after { height: 40px; box-shadow: 5px 0 0 #fde428, 5px 180px 0 #fde428; } .text h2{ position: absolute; color: white; top: 10%; transform: translateX(-60%); } .text p{ position: absolute; bottom: 15%; transform: translateX(-50%); text-transform: uppercase; color: #fde428; cursor: pointer; border-bottom: 2px solid #fde428; }

Bootstrap 4: зачем нужен метод $('.alert').alert()

Приведённый пример (скопирован 1 в 1 из документации) состоит из одного лишь только HTML-кода. Alert прекрасно закрывается без единой строчки самостоятельно написанного JS-кода (пример на JSFiddle).


Но тогда возникает вопрос: зачем же нужен метод $('.alert').alert()? В документации сказано:
Not necessary when using the data-api’s auto-initialization.
но я не понял, что это за data-api’s auto-initialization


Ответ

Бутстрап предусмотрел два способа использовать свои JS плагины:
Написать скрипт с помощью методов и событий из документации Бутстрапа. Расставить атрибуты data, как указано в документации.
Во втором случае Бутстрап запустит всё сам, а данные, необходимые для инициализации и работы, возьмёт из data атрибутов. Именно это и подразумевает фраза, которую вы процитировали.
Вы можете выбрать, какой способ вам больше подходит, или объединить их: базовое поведение инициализировать через data атрибуты, а остальное запрограммировать скриптом.
Авто-инициализация не сработает, если HTML-блок добавляется скриптом после загрузки страницы. Тогда придётся запускать вручную, через $('.alert').alert(), например.
И, если нужно, авто-инициализацию можно отключить полностью
$(document).off('.data-api')
или для какого-нибудь конкретного плагина
$(document).off('.alert.data-api')

Как в обобщенном классе (generic) задать ограничение “только float или int” для типа?

Есть класс Parameter
public abstract class Parameter { public T Value { get; } //... }
Как в таком классе для типа T задать ограничение только на определенные базовые типы? Хотелось бы иметь что-то наподобие этого:
public abstract class Parameter where T : int, float, double, string { public T Value { get; } //... }
IntelliSense сразу ругается на каждый тип:
"int" не является допустимым ограничением. Тип, использованный в качестве ограничения, должен быть интерфейсом, незапечатанным классом или параметром-типом.
UPD. Или просто оставить тип без ограничений и ничего страшного в этом нет, что можно случайно создать класс с не таким типом, который ожидалось видеть?
UPD 2. Отвечаю на вопрос для какой цели нужно ограничение типа. Есть некоторая абстракция Параметр, которая инкапсулирует в себе данные определенного базового типа. У него есть поля Значение, Имя и Максимальное и минимальное значение. Читая ответы на вопросы, я понял, что нет смысла ограничивать данный тип параметра.


Ответ

Есть несколько причин, по которым этот код не может работать в C#
where T : int, float, double, string
Когда вы указываете ограничение T : Type то это значит, что T может быть как типа Type так и потомком типа Type. Следовательно, конструкция where T : int, float семантически означает следующее — тип T должен наследовать от типов int и float. Это не сработает по двум причинам:
В C# запрещено множественное наследование Конструкция T : int не может работать, так как int это структура, а структуры не поддерживают наследование. Это свойство классов. Можете проверить это на примере: Generic where T : struct where U : T. (замените struct на class и все заработает)
Зато компилятор предлагает вам рабочие варианты:
Тип, использованный в качестве ограничения, должен быть интерфейсом, незапечатанным классом или параметром-типом.
Cтруктуры и классы могут имплементировать интерфейсы, поэтому ограничение типа на интерфейс может иметь смысл как для структур, так и для классов, например в ограничение T : IComparable можно подставить как int так и string так как оба этих типа имплементируют этот интерфейс.
Или просто оставить тип без ограничений и ничего страшного в этом нет, что можно случайно создать класс с не таким типом, который ожидалось видеть
Для этого следует ответить на вопрос, для чего вы задаете ограничение типа? Вы видите что-то общее между типами int и string? Вы хотите обращаться к общим членам этих типов или использовать их как-то иначе в полиморфном контексте? Если нет, то, наверное, и нет смысла искусственно ограничивать тип-параметр.

Как программно получить список всех разрешений (permissions) из Android Manifest

В связи с тем, что с 1 ноября 2018 года обязали во всех опубликованных в Google Play Market приложениях установить "targetSdkVersion=26", остро встает необходимость обработки всех разрешений приложения.
В связи с этим, стало актуальным получение списка наименований всех разрешений из Манифеста с дальнейшей их обработкой.
Подскажите какими способами это можно осуществить!?


Ответ

Utility класс, который позволяет получать разрешения, используемые в файле манифеста
public final class PermissionUtils {
private PermissionUtils() { }
/** * Retrieves permissions listed in the manifest file * @param context Context * @return Returns String array of permissions */ public static String[] retrievePermissions(Context context) { try { return context .getPackageManager() .getPackageInfo(context.getPackageName(), PackageManager.GET_PERMISSIONS) .requestedPermissions; } catch (PackageManager.NameNotFoundException e) { throw new RuntimeException("This should have never happened.", e); } } }

Как объявить один класс в нескольких файлах в C#

Как объявить один класс в нескольких файлах в C#


Ответ

C# поддерживает частичные классы. Для того чтобы объявить частичный класс, необходимо добавить модификатор partial в объявление класса. Во втором классе это выглядит идентично. Например. FirstPart.cs partial class SomeClass { // Определение класса 1 } SecondPart.cs partial class SomeClass { // Определение класса 2 }

Как определить размер файла в программе на C?

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


Ответ

Нужно использовать функцию fstat. #include #include #include #include #include #include #include
int main() { void *buffer = NULL;
int descriptor = open("filename", O_RDONLY);
if (descriptor != -1) { FILE *file = fdopen(descriptor, "rb");
if (file) { struct stat statistics;
if (fstat(descriptor, &statistics) != -1) { buffer = (char*)malloc(statistics.st_size); } fclose(file); } close(descriptor); }
if (!buffer) { free(buffer); }
return 0; }

Установка Linux в D-Link

Интерестно, есть ли на форуме люди, которые представляют себе, как собрать Линуксовое ядро и установитить его в маршрутизатор D-link, ну или любой другой!?


Ответ

Задача сборки прошивки для девайса(роутер или что-то еще,- не важно) вообще говоря достаточно сложна: Чтобы собрать прошивку надо иметь исходники ядра, rootfs и тематического софта(того, который делает железки разными: веб-интерфейсы, приложения и т.п.). Скорее всего Ваша железка не содержит процессора х86 семейства. Соответственно Вам потребуется набор кросстулов(gcc, binutils) для компиляции ядра на x86 хост-машине. Скорее всего у Вас нет такого набора тулов от производителя железки, т.е. придется сначала собрать тулы. Уже на этом первом шаге у Вас могут возникнуть проблемы, типа: есть вероятность, что Вы не сможете найти правильный пакет gcc, который сможет генерить код на Вашу target железку. Если Вы нашли и собрали кросстулы, следующий пункт сборка ядра, модулей ядра(если они есть) и rootfs, если ее нет готовой. Здесь проблема в том, что у Вас скорее всего нет исходников всех необходимых драйверов/модулей (хотя может для роутера найдется все - я хз). Следующий пункт сборка приложений(если они есть), конфигурирование и укладка всего что есть в target файловую систему для сборки образа для заливки(это если у Вас прошивка единим образом кладется. Бывают случаи когда ядро и rootfs отдельно, а все остальное отдельно ставится уже после установки ядра и rootfs). Теперь если у Вас образ для заливки на руках, то надо разбираться со способом залики образа на коробку, мне известны следующие варианты: поднимаем на хосте прошивочный сервер, соединяем железку с хостом езернетом - жмем кнопки на железке и включаем ей питание. После начала процеса прошивки отпускаем кнопки. записываем образ на USB-флеху, втыкаем в железку USB-флеху, жмем кнопки - вкл. питание. используем JTAG - шьем аппаратно. загружаем железку в bootloader(сюда заходим через сериал-терминал), в бутлоадере скачиваем прошивку через tftp, там же прошиваем. загружаем железку в bootloader, в бутлоадере монтируем образ ядра через nfs, загружаемся в линукс с nfs. В процессе сборки/прошивки могут возникать следующие проблемки: криво собрались/прошились,- бутлоадер в наличии - пересобираемся/прошиваемся заново) криво прошились,- убили бутлоадер,- железка не встала - ищем JTAG) криво прошились,- железка не встала, сдохла флеха на железке - несем ее на свалку) Вобщем процесс увлекательный))

Память JVM: как оптимизировать многопоточное приложение?

Господа, насколько я понимаю модель памяти JVM выглядит так: если поток вызывает некий метод класса, то все локальные переменные которые там используются будут созданы не в HeapMemory, а в StackMemory. Этот StackMemory тоже очищается GC и тоже входит как слагаемое в полную доступную JVM память (ее можно получить как Runtime.maxMemory()), и, следовательно, чем больше потоков - тем больше занято памяти, даже при том что HeapMemory остается без изменений. Т.о. можно записать: Runtime.freeMemory() = Runtime.maxMemory() - Thread1Stack - Thread2Stack - ... - HeapSpace. Поправьте меня, пожалуйста, если я не прав. К чему я это спрашиваю: в моем приложении есть специальный поток-наблюдатель, который все время логгирует значение Runtime.freeMemory() и иногда оно опускается до сотен байт (однажды вообще было Runtime.freeMemory() = 8 ). Это приводит к тому, что процесс замедляется и Томкат не отвечает на HTTP запросы. Возникает вопрос: может ли при таком низком значении памяти запускаться GC? Я предполагаю, что должна быть связь оптимального количества потоков не только с количеством процессоров, но и с размером памяти. Как мне определить эту связь? У меня Томкату доступно Runtime.maxMemory() = 64МБ, при этом обычно мое приложение запускает 3-4 потока, максимум до 10-12. Мне казалось, что такая нагрузка подходит для процессора т.к. все эти мои потоки очень много спят. Однако судя по тому как мало памяти остается - думать надо не только о процессоре, но и о памяти. Итак, как понять какое количество потоков оптимально для многопоточного приложения? Какие кроме Runtime.freeMemory() методы отслеживания состояния памяти вы используете? (я не могу запустить профайлер на удаленном хостинге).


Ответ

Вы не правы. Объекты всегда создаются в куче. В стеке живут примитивные типы (byte, char, short, int, long, boolean). В стеке хранятся ссылки на объекты в куче. Все ваши последующие рассуждения, как следствие, не верны. Если у вас всё встревает или даже падает по OOM, то у вас утечка. В общем, количетсво потоков и память связаны только когда потоков очень много (тысячи). Кроме того, каждому потоку можно указать конкретный размер стека, если вы знаете, какова максимальная требуемая глубина и нет рекурсии. Так что количетсво потоков выбирается таким образом, чтобы оно по возможности не было пропорционально количеству данных приложения и количеству пользователей. Что же до трёх потоков, то вы забываете о самом томкате, который запускает... очень немало потоков (в зависимости от конфигурации).

Шаблонизаторы vs быстродействие, удобство, гибкость

Надеюсь, что не подниму сейчас холивар) В общем-то всегда удивлялся фанатам шаблонизаторов и хочется послушать аргументы в их пользу. Не понимаю, какой смысл в написании псевдокода на псевдоязыке, который либо компилируется, либо (омфг) транслируется во время запроса к странице, который к тому же реально сложнее для восприятия. Скомпилированный код того же smarty, по сравнению с нативным шаблоном, захламлен чем-то явно лишним, сам код намного менее гибок, чем php, малопонятные конструкции циклов, пляски с бубном на банальном разделении контента в 3 столбика, etc etc... Но при этом даже здесь от "старожилов" и явно не глупых людей слышу постоянно "используйте шаблонизаторы типа Смарти". Итак, вопрос: а, собственно, зачем? ЗЫ: Я не против шаблонизаторов в принципе(только извращений типа псевдокода с "компиляцией"). То, с чем я работаю, работает по такому принипу (минимальный код): function assignTemplate($file, $tmpl, $params = array()) { ob_start(); if (!is_file($file)) { echo 'No file'; } elseif(!is_file($tmpl)) { echo 'No template'; } else { require $file ; ob_end_clean(); ob_start(); require $tmpl ; } $result = ob_get_contents(); ob_end_clean(); return $result; }


Ответ

Суть шаблонов, - абстрагировать верстку от кода на PHP, облегчить верстальщикам (а не программистам) работу. По чему не стоит писать свой шаблон координально синтаксически отличающийся от сматри и иже с ним? Дело в том, что верстальщику легче привыкнуть к одному языку шаблонов (или использовать его подмножество), чем под каждый проект изучать свой (особенно если он на жизнь зарабатывает фрилансом). Мощные шаблонизаторы по типу смарти, благополучно транслируют свой код в пхп и кэшируют его (поэтому замедление будет заметно только при трансляции нового шаблона в код, дальше все будет работать из кэша). Да, он не читаемый, но он и не должен быть читаем человеком, для человека есть текст шаблона, который он должен изменять. P.S. Могу поспорить каждый писал свой шаблонизатор, еще и потому что это легче чем изучать чужой и пользоваться им (прошу не обижаться, я сам такой :) ).

Приобретение реальных навыков в программировании

Появилась потребность в приобритении практических навыков в програмировании (язык Java). Т.к. прочтением разной литературы + статей, на одних задачах по ООП далеко продвинуться крайне сложно, ведь зачастую даже от juniora требуется знание сторонних технологий, фреймворков. Хотелось бы узнать какой-нибудь ресурс, где таких вот начинающих людей берут либо на проекты open source, либо просто дают хорошие практические задания, например как эти задания. Стоит цель самосовершенствования в программировании. Подскажите что-нибудь, как быть, что делать. В большей части интересует web-программирование.


Ответ

Вот пара задач. Написать сайт на JSP/JSF, можно копнуть EJB. Прикрутить к нему AJAX и MySQL/Oracle DBMS/подставить свое. Думаю, этого для джуниора достаточно. PS. Все это Java EE.

Java Core - что нужно знать? [закрыт]

Что нужно знать, чтобы можно было сказать "Я знаю Java Core"?


Ответ

Ну на самом деле понятие Java Core очень расплывчатое. Кто-то считает, что это все то, что описано в JLS, кто-то берет за основу SCJP, кто-то какие-то собственные метрики. Есть вообще люди, которые называют это Java Fundamentals, а к Core относят еще и ООП, работу с коллекциями и основы мультипоточности. Тут здесь все очень субъективно. Но думаю, если сможете ответить на все вопросы из этого интервью, то вполне уверенно можете говорить о том, что знаете Java Core.

C++ и вставки ассемблера

Я недавно выучил С++ на базовом уровне (стандартная библиотека+STL). Решил немного подучить ассемблер (когда-то учил его, до конца так и не осилил). Собственно вопрос, какие преимущества дают асм-вставки в С++ код, и как это оформить. P.S. Всех с новым годом!


Ответ

Преимущества: Возможность оптимизации вручную Использование (опять же для оптимизации) команд процессора, недоступных через стандартные средства С++ В случае программирование ядер - низкоуровневый доступ к оборудованию через порты ввода-вывода, к процессорным прерываниям для создания слоя абстракции. и др. подобное Как оформлять - зависит от компилятора и платформы. С Новым годом!

Нагрузка PHP-интерпретатора

Несколько вопросов к людям, хорошо понимающим работу интерпретатора PHP. Сказывается ли на скорости выполнения скрипта количество открывающих дескрипторов? Т.е. в файле смесь из HTML разметки и PHP кода, при этом скажется ли существенно на производительности, если мы будем открывать и закрывать на каждой строке? Этот: 0 ) { echo 'yes'; } else { echo 'no'; } ?> или 0 ) { ?> Есть ли разница, по скорости выполнения интерпретатором, классического синтаксиса и альтернативного? Т.е. между таким: 0 ) { echo 'yes'; } else { echo 'no'; } ?> и таким: 0 ): echo 'yes'; else: echo 'no'; endif; ?> вариантами. Какой из вариантов вывода переменной и результатов функции использует меньше ресурсов, если вообще есть разница? Этот: или этот:


Ответ

0) { echo $e; } else echo $e; } echo '
'.(microtime(1)-$st);
$st = microtime(1); for ($i = 0; $i < 1000000; $i++) { ?> 0) { ?> '.(microtime(1)-$st); echo '


'; $st = microtime(1); for ($i = 0; $i < 1000000; $i++) { ?> 0) { ?> '.(microtime(1)-$st);
$st = microtime(1); for ($i = 0; $i < 1000000; $i++) { ?> 0) { ?> '.(microtime(1)-$st); echo '
'; ?> Результат: 0.08100700378418 2.4613921642303 ---- 3.0508909225464 2.4576618671417 Последние 2 менялись от "1.5/6" до "4/1", так что скорее одинаковые. А вот первая пара - говорящая) UPDATE, синтаксис 0) { echo $e; } else echo $e; } echo '
'.(microtime(1)-$st);
$st = microtime(1); for ($i = 0; $i < 1000000; $i++) { if (1 > 0): echo $e; else: echo $e; endif; } echo '
'.(microtime(1)-$st); echo '
'; ?>
0.089139938354492 0.082063913345337

Ленивая подгрузка сообщений из базы

Всем привет! Заметил такую проблему, которая мешает удобству на сайте. Происходит подгрузка дополнительных сообщений (по 10 штук) в div. Если перейти далее (по ссылке) и после нажать назад (в браузере), то подгруженные сообщения ранее исчезают, не отображаются. Их приходится подгружать заново. На многих сайта (примерно с такой же системой) работает без такой проблемы. Подгрузка осуществляется путем скролла. Скорее всего проблема решается с помощью кеширования, но это всего лишь догадки. Код: javascript: HTML. Выводится 10 первых сообщений путем foreach. После цикла php идет див для подгрузки новых сообщений:

Сообщений больше нет.


Ответ

Используйте хеш. Т.е. на кнопках постранички ставите, к примеру ID, в котором есть номер страницы, а в JS по клику вытаскиваете этот номер страницы и устанавливаете хеш. Например, у вас кнопки постранички имеют класс paginal и ID pn-1, pn-2 и т.д.: $('.paginal').click(function(e){ var arrId = $(this).attr("id").split('-'); var numPage = parseInt(arrId[1], 10); // Номер страницы, можно использовать для чего-то еще location.hash = "pn" + numPage; // Устанавливаем хеш });

Правильная проверка кода (code inspection)

Здравствуйте, ХэшКодовцы! Стоит задача проинспектировать некоторый достаточно объемный C++ код, который не может быть откомпилирован (нами). Т.е. грубо нам доступен исходный код и готовое решение в виде устройства, с интегрированным кодом. Необходимо найти возможные ошибки, связанные с переполнением буфера в сим коде. Так как знания C++ у меня заканчиваются на уровне простейших задач и алгоритмов, хотя по большому счету в данном проекте больше и не нужно, хотел бы спросить, как наиболее оптимально выполнить сей поиск? Понятное дело, что особое внимание необходимо уделить любым видам массивов и копированию памяти, но как быть оптимальным? Спасибо.


Ответ

Воспользоваться каким-либо решением для статического анализа кода, лично я рекомендую PVS Studio. Возможно, Вы также обнаружите какие-либо другие ошибки, потенциально приводящие к прописи в памяти. Найти и тщательно проанализировать все референсы на небезопасные функции типа memset, memcpy и т.п. Сделать поиск по числовым константам в коде, проверить все места использования переменных типа int, std::size_t и их альясов, которые могут потенциально приводить к вычислению неправильного смещения в буферах памяти, и, как следствие, ошибкам. (Идеальный вариант в вакууме) Собрать небольшой тестовый фреймворк и отдельно скомпилировать и протестировать критичные к ошибкам компоненты кода. В случае, если Вам удастся реализация тестового сендбокса / mock-объекта, то ошибки типа buffer overflow можно элементарно словить классическими способами - CrtDbg или valgrind. В случае, если есть тестовый фреймворк, то может также подойти методика fuzzing-тестирования. Все, естественно, зависит от качества review который вы надеетесь получить в итоге. Вообще говоря, нахождение ошибок типа buffer overflow в произвольно взятом коде без возможности его скомпилировать - это не самая простая задача. Может быть все-таки существует способ каким-либо образом собрать данный код под дебажным рантаймом с автоматическим нахождением memory leak'ов и прописей мимо памяти?

Онлайн-трансляции через веб-камеру в реальном времени

Ребята, подскажите решение по онлайн трансляции через веб-камеру в реальном времени (с php). Можно ли обойтись без "видео хостинга"? За хороший совет уважуху обеспечу.


Ответ

снимаем изображение с камеры и ложим в место доступное из вне. А из вэба запрашиваем эту картинку. в html постоянно обновляем эту картинку через javascript. вот и всё.