• Оптимизируем, оптимизируем и еще раз оптимизируем

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

      Date

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

          public boolean isValid(Date start, Date end) {
              Date now = new Date();
              return start.before(now) && end.after(now); 
          }
      

      Казалось бы — вполне очевидное и правильное решение. В принципе, да, за исключением двух моментов:
      • Использовать Date сегодня в java — уже, пожалуй, моветон, учитывая тот факт, что почти все методы в нем уже Deprecated.
      • Нету смысла создавать новый объект даты, если вполне можно обойтись примитивом long:

          public boolean isValid(Date start, Date end) {
              long now = System.currentTimeMillis();
              return start.getTime() < now && now < end.getTIme(); 
          }
      


      SimpleDateFormat

      Очень часто в веб проектах возникает задача перевести строку в дату или наоборот дату в строку. Задача довольно типичная и чаще всего выглядит так:

          return new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z").parse(dateString);
      

      Это правильное и быстрое решение, но если серверу приходится парсить строку на каждый пользовательский реквест в каждом из сотен потоков — это может ощутимо бить по производительности сервера в виду довольно тяжеловесного конструктора SimpleDateFormat, да и помимо самого форматера создается множество других объектов в том числе и не легкий Calendar (размер которого > 400 байт).

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

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

      Но решения есть и их как минимум 2:
      • Старый, добрый ThreadLocal — cоздаем SimpleDateFormat для каждого потока 1 раз и переиспользуем для каждого последующего запроса. Данный подход поможет ускорить парсинг даты в 2-4 раза за счет избежания создания объектов SimpleDateFormat на каждый запрос.
      • Joda и ее потокобезопасный аналог SimpleDateFormat — DateTimeFormat. Хоть йода в целом и медленнее дефолтного Java Date API в парсинге дат они идут наравне. Несколько тестов можно глянуть тут.

      Читать дальше →
    • Организуем выделение текста в textarea

      • Tutorial
      Добрый день.

      В разработке интерфейсов иногда можно встретиться с задачей выделения вводимого пользователем текста в зависимости от определенных условий. (Например, была реализована серверная проверка грамматики, либо необходимо выделять определенным цветом те или иные слова\участки и т.д.)
      Однако, элемент textarea не поддерживает html\bb теги. Как один из способов решения — использование contenteditable в элементах div.
      В данной небольшой статье я предлагаю более-менее подробно рассмотреть способ выделения текста, используя textarea.
      Читать дальше →
    • Публикация артефакта в Maven Central через Sonatype OSS Repository Hosting Service

      На написание этой статьи меня сподвигла некоторая разрозненность источников информации по такой
      важной, на мой взгляд, теме, как публикация своих артефактов в Maven Central. Конечно, следует
      отдать должное сотрудникам Sonatype: их официальный гайд (ссылка в конце статьи) достаточно полно
      описывает весь процесс. Но в нём нет некоторых неочевидных тонкостей (вроде проблемы хранения
      паролей), и он сам выглядит немного неряшливо. На русском же языке на эту тему ресурсов я не нашёл в
      принципе. Лично для меня это не страшно, но многих это может остановить.

      Внимание, много текста
    • Предельная производительность: C#

      performanceЯ поделюсь 30 практиками для достижения максимальной производительности приложений, которые этого требуют. Затем, я расскажу, как применил их для коммерческого продукта и добился небывалых результатов!
      Приложение было написано на C# для платформы Windows, работающее с Microsoft SQL Server. Никаких профайлеров – содержание основывается на понимании работы различных технологий, поэтому многие топики пригодятся для других платформ и языков программирования.
      Читать дальше →
    • Коллаборативная фильтрация

        В современном мире часто приходится сталкиваться с проблемой рекомендации товаров или услуг пользователям какой-либо информационной системы. В старые времена для формирования рекомендаций обходились сводкой наиболее популярных продуктов: это можно наблюдать и сейчас, открыв тот же Google Play. Но со временем такие рекомендации стали вытесняться таргетированными (целевыми) предложениями: пользователям рекомендуются не просто популярные продукты, а те продукты, которые наверняка понравятся именно им. Не так давно компания Netflix проводила конкурс с призовым фондом в 1 миллион долларов, задачей которого стояло улучшение алгоритма рекомендации фильмов (подробнее). Как же работают подобные алгоритмы?

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


        Читать дальше →
      • Новые источники данных для Teiid, часть 2: пишем транслятор

          В предыдущей части мы коротко рассмотрели способ описания источника данных при помощи DDL. Но что делать, если источник использует специфический протокол? Если прямого отображения данных недостаточно? Если мы хотим добавить предобработку данных или встроенную процедуру? Выход есть: написать транслятор.

          В общем случае транслятор состоит из 4 частей (классов). Это — наследник класса ExecutionFactory и реализации интерфейсов ResultSetExecution, ProcedureExecution и UpdateExecution; кроме этого, штатные трансляторы Teiid для удобства выделяют в отдельный класс обработчик метаданных (metadata processor), хотя он никакого интерфейса не реализует и ни от чего не наследуется. Рассмотрим всё по порядку.
          Читать дальше →
        • Android: Обработка СМС

          0. Вместо вступления


          Периодически (когда у меня выпадает свободный вечер, и наш «клуб» организует игру) я играю в регбол. «Клуб» организован таким образом, что в день игры всем участникам приходит СМС такого вида:

          Регбол! Сегодня в 19-30. Двор школы №30: ул. Володарского, 20. Открытая площадка с резиновым покрытием. Тел. 8 (951) ***-**-**.

          И вот я подумал — почему бы не написать небольшое приложение, которое будет отлавливать эти сообщения, и забивать их в гугл-календарь. Зачем? Да, в основном, just for fun, ибо я не настолько занятой человек, чтобы мне были жизненно необходимы автоматические секретари.

          Итак, приложение будет уметь следующее:
          • Следить за входящими сообщениями. Если пришло сообщение от адресата RM FIGHT, то нужно сверить текст сообщения с шаблоном, и при совпадении создать мероприятие в гугл-календаре. Если же текст сообщения с шаблоном не совпадает (например, просто какие-то новости пришли), то сохраняем сообщение в базе, чтобы потом можно было его прочитать.
          • Показывать сообщения от этого адресата, не попадающие в категорию «Оповещение об игре» (новости, реклама и т.д.).

          В рамках статьи я полагаю, что у читателя есть базовые знания — как создать проект, что такое файл Manifest, и с чего вообще начинать разработку под андроид — на этот счет есть куча разных туториалов, и здесь на этом останавливаться не будем. В то же время статья не предназначена для продвинутых андроид-девелоперов, в ней будут рассматриваться достаточно базовые вещи, вроде мониторинга и обработки смс, работы с базой данных, подключения по HTTP.
          Читать дальше →
        • Рецепт настройки удалённого мониторинга контейнеров Tomcat и Jetty штатными средствами JDK

            Проводя уже около 6 лет собеседования с Java-разработчиками заметил, что из приходивших кандидатов вообще никто не знает, что можно штатными средствами JDK удалённо мониторить состояние JVM с контейнерами сервлетов.
            Поэтому далее пошаговый рецепт, как настроить и использовать эту замечательную возможность
            Читать дальше →
          • Использование разделяемой памяти в Java и off-heap кеширование

              На прошлой неделе состоялся успешный эксперимент по запуску нового решения для download-сервиса. Один достаточно скромный сервер (2 x Intel Xeon E5620, 64 GB RAM) под управлением Java-приложения собственной разработки принял на себя нагрузку восьми Tomcat'ов, обслуживая более 70 тысяч HTTP-запросов в секунду общей пропускной способностью 3000 Mb/s. Таким образом, весь трафик Одноклассников, связанный с пользовательскими смайликами, обрабатывался одним сервером.

              Вполне естественно, что высокие нагрузки требовали нестандартных решений. В цикле статей о разработке высоконагруженного сервера на Java я расскажу о проблемах, с которыми нам пришлось столкнуться, и о том, как мы их преодолели. Сегодня речь пойдет о кешировании изображений вне Java Heap и об использовании Shared Memory в Java.
              Читать дальше →
            • Вебинар: Основы использования паттерна Page Object вместе с Selenium WebDriver

                Это пятый вебинар из цикла бесплатных вебинаров по автоматизации тестирования.
                Видеозапись (продолжительность 1 час 5 мин.):

                Темы и детали видеозаписи под катом
                Читать дальше →
                • +12
                • 7,1k
                • 2