субота, 6 жовтня 2012 р.

Making your Mac fit


So today I again started my morning staring at how Spotlight indexes my Mac again, condemning all other apps, including my precious IDEA to lag. Something ought to be done by this. Lion is so full of bullshit.

So here are few things I've done to make my life faster and with less shit around.

First I wanted to disable Spotlight. I found that I can replace it with QuickSilver (http://qsapp.com/)

QS is just a better Spotlight, with much more control over what happening behind the scenes on your Mac. From start it defaults to searching only application, which is just what I want from this kind of applications..

To seamlessly replace Spotlight with it, you need to disable the latter:

sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.metadata.mds.plist

In case you will want it back, you can reenable it with

sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.metadata.mds.plist

I hope this day will never happen.

Now you've got ^+Space combination freed, and you can reassign default QS shortcut to be just that. With a little bit more effort, you can hide QS from Dock and Menubar, so it will be totally ubiquitous, showing up to you only when you need it and not disturbing otherwise.

The only last thing is something should be done with Spotlight icon in Menubar and having power of google it's easy:

sudo chmod 600 /System/Library/CoreServices/Search.bundle/Contents/MacOS/Search

Next, you kill a process called SystemUIServer to refresh the menubar and have the change take effect:

killall SystemUIServer

Getting the Spotlight icon back is a matter of bringing the permissions back to their default setting:

sudo chmod 755 /System/Library/CoreServices/Search.bundle/Contents/MacOS/Search

Follow this up with killing the SystemUIServer again:

killall SystemUIServer

So that's it and now you don't have to wait seconds until you run some application you need right now, just because Spotlight is very busy doing it's important indexing.

The next thing I wanted to get rid of is a Dashboard. This just pisses me off when I press F12 accidentally and it goes up in the hottest moment driving me nuts.

With just a couple of simple terminal commands you can be rid of the Dashboard forever.

defaults write com.apple.dashboard mcx-disabled -boolean YES

killall Dock

Not only this will give you back your CPU cycles, RAM and precious keyboard shortcut, but also remove the annoyance of getting Dashboard at the most unpleasant moment.

If you think you've made a biggest mistake in your life doing the above, you can aways get that piece of crap back with reverting the setting

defaults write com.apple.dashboard mcx-disabled -boolean NO

killall Dock

And yes, finally I did empty my Trash ;)

So far so good, it's not the best optimizations, however my day to day work will be with much less trouble.

Thanks to:

[1] http://osxdaily.com/2011/12/10/disable-or-enable-spotlight-in-mac-os-x-lion/
[2] http://osxdaily.com/2011/12/12/hide-spotlight-menu-icon-mac-os-x-lion/
[3] http://www.psyion.net/tutorials/3751







четвер, 3 листопада 2011 р.

Вдогонку Zookeeper Tech Talk

Свежак с очередного тектолка в Cogniance - презентация с моего доклада о Zookeeper. Спасибо Стэну Шилко - тема очень клевая. Заметил за собой страсть к выступлениям - зарядило очень сильно, надеюсь всем тоже было интересно, хотя может и не везде понятно :)

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

Из ответов на вопросы - нашел две реализации высокоуровневых примитивов: KeptCollections и Menagerie. Они больше дополняют друг друга, чем конкурируют, но более близко с ними познакомлюсь позже.

Из планов на последующие Java Evenings - обзор KeptCollections и Menagerie, попробую покодить что-то свое и представить кое какие рекомендации по использованию Zookeeper'а

Как обычно ссылка на слайды: http://goo.gl/Pwcfj 



понеділок, 17 жовтня 2011 р.

Вдогонку java.util.concurrent Tech Talk

Во вторник 11-го октября отгремел очередной Java Evening в Cogniance c пиццей, пивом, интересными людьми и интересными темами. Среди героев дня был и я со своим докладом по java.util.concurrent, В прошлом (и первом) Java Evening у меня не вышло поучаствовать, зато на этот раз я без лишней скромности откусил из общего времени целых 80 минут вместо положенных 15ти!

Выступать мне не впервой - участвовал когда-то в конференции OSDN, но это было до войны при немцах. Ну и конечно же, защита диплома - чем не бесценный опыт :)

Но в качестве Java-разработчика - это мое первое публичное явление народу. Да и тема была не самая легкая - почему то java.util.concurrent, хоть она и у всех на слуху, молча обходят стороной.  В общем пришлось постараться - подготовил и теории выше крыши, и примеров приготовил для иллюстрации.

Сам заметил, что не слежу за временем абсолютно, но вроде никто не был против, аудитория казалась заинтересованной, - настолько, насколько я мог оценить своим затылком (сидел я с ноутбуком, чтобы удобно было показывать код, и следить за аудиторией не было никакой возможности)

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

Теперь без лишней скромности могу сказать, что готов читать книгу Гетца. Заказал ее на следующий же день. Мультипоточность на этом для меня только начинается - впереди архипелаг Java Memory Model, который и станет основной темой моих будущих писаний.

Nevertheless, выкладываю слайды и примеры, дабы увековечить этот великий исторический момент.

Качаем, смотрим, изучаем, спрашиваем. Сразу скажу что AtomicCyclicCounter - неверно написан полностью :) Пишите свои варианты почему, выигравшему - автомобиль!

Так же в презентации, на третьем слайде - Они. Как зовут каждого, тоже пишите в комментарии, первому счастливчику - автомобиль!

Смотреть слайды 
Смотреть примеры - это SVN-репозиторий, можно сделать read-only checkout










пʼятниця, 16 вересня 2011 р.

Avoid SSLException with all-trusting TrustManager

Anyone who stumbled upon SSL in their day-to-day Java joy, know that by default Java is very picky about certificates on the other end. Whether you want to submit a HTTP request to the site with expired certificate (yes, people change them, and they may forget to do that) or happen to work against an endpoint with self-signed certificate (not everyone are ready to blindly give hundreds of bucks for those expensive bits), you'll be kindly refused (if SSLException can be described as kind)

In such cases you should find some way around the issue to make things work.Whenever its about the remote service, I preferred to maintain a separate truststore for the project, but having a headache of keystores during development is a motivation killer.

Here is how you can avoid JVM to check peer certificates for validity. The below code will accept any SSL certificate presented, this means - no security unless you know what you're doing. Generally this property switch will be of great use at development time or debugging time.

import java.security.cert.X509Certificate;

// ...

if ("true".equalsIgnoreCase(System.getProperty("trust.ignore", "true"))) {
	TrustManager[] trustAllCerts = new TrustManager[]{
		new X509TrustManager() {
			public X509Certificate[] getAcceptedIssuers() {
				return null;
			}
			public void checkClientTrusted(
				X509Certificate[] certs, String authType) {
			}
			public void checkServerTrusted(
				X509Certificate[] certs, String authType) {
			}
			public boolean isClientTrusted( X509Certificate[] cert) {
				return true;
			}
			public boolean isServerTrusted( X509Certificate[] cert) {
				return true;
			}
		}
	};

	// Install the all-trusting trust manager
	try {
		SSLContext sc = SSLContext.getInstance("SSL");
		sc.init(null, trustAllCerts, new java.security.SecureRandom());
		HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
	} catch (Exception e) {
	}
}

пʼятниця, 9 вересня 2011 р.

java.util.concurrent Tech Talk

Я тут подписался на Tech Talk о java.util.concurrent с целью нести свет в массы. Тема довольно интересна мне и довольно давно, но играть в КО не хочется и тратить время на то, что всем известно, когда можно с гораздо большим удовольствием есть пиво - тоже. Поэтому я добросовестно подготовил предварительный список тезисов для освещения. Комментарии и предложения - приветствуются.

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

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

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

Итак агенда:

0. Интро
Введение в многопоточность - зачем, почему, когда и как - в общем короткое вступление, без которого никак
Кратко о базовых конструкциях языка для поддержки многопоточности - о Thread, Runnable, мониторах, synchronized-блоках. Тут же пример кода. Пару слов о Vector, Hashtable и synchronized-коллекциях
Мотивация к старту JSR166, картинки с мордами Дага Ли, Брайана Гетца, Дийкстры, Хоара и Бринч-Хансена

1. Подходы
Блокирующая и неблокирующая многопоточность - в чем разница

1.1. Блокирующая многопоточность
ReentrantLock vs native Java locks
Lock & Condition, тут же упомянем TimeUnit и как в ХХI веке спят потоки
Semaphore

1.2. Неблокирующая многпоточность
Atomic типы и как они устроены, CAS, пример кода
Атомарные операции на сложных shared state, про разные AtomicReference, пример кода
Краткое сравнение подходов

2. Распределение работы

Executor, ExecutorService, Сallable, Thread-пулы
Fork/Join framework (привет семерочка)
пример кода

3. Конкуррентные типы данных в JSR166

Опять слегка вспомним про Atomic типы
CopyOnWriteArrayList, ConcurrentHashMap, ConcurrentSkipListMap, ConcurrentSkipListSet, CopyOnWriteArraySet
перформанс Vector, Hashtable vs sync collections vs CopyOnWriteArrayList, ConcurrentHashMap - где то в закладках были графики
Немного об итераторах
Генерация случайных чисел, ThreadLocalRandom

4. Очереди
blocking queues and deques

5. Синхронизация потоков
CountDownLatch, CyclicBarrier, Exchanger

6. Что еще есть в мире Java кроме JSR166 - вот это не обещаю что успею, но если очень будет интересно, постараюсь
Disruptor http://code.google.com/p/disruptor/
NonBlockingConcurrentHashMap, http://sourceforge.net/projects/high-scale-lib

7. Чего ждать в Java 8 - тоже по заявкам
jsr166e: http://dhruba.name/2011/08/28/jsr166e-upcoming-java-util-concurrent-apis-for-java-8/

8. Q&A не планирую - все вопросы по ходу дела, в заключение забросаю книгами и ссылками.

субота, 27 серпня 2011 р.

Lock та Condition

Минулого разу я розглянув Atomic-типи та методику їх застосування. Сьогодні я продовжу огляд класів з пакету java.util.concurrent. Отже Lock та Condition.

У JDK 7 три реалізації Lock’ів, але нас цікавить лише ReentrantLock, тому далі мова йде саме про цей клас. Інші два використовуються вкупі з ReadWriteLock, і з точки зору можливостей не дуже цікаві. ReadWriteLock буде темою однієї з наступних статей.

Чим корисні високорівневі локи?
Як відомо у Java кожен об’єкт є простеньким монітором. Більш точно Java-монітор є простим монітором Хоара з однією внутрішньою умовною змінною. З іншого боку - клас ReentrantLock, який виконує ту саму функцію. Я спочатку задавався питанням, навіщо вводити ще й високорівневу конструкцію, яка робить те саме, адже завжди можна ввести змінну типу Object і використати її для синхронізації. 

Але сенс у тому є - перевагаю локів є можливість умовного блокування tryLock(), можливість будувати повноцінні монітори з багатьма множинами очікування використовуючи інтерфейс Condition та багато інших зручностей.

По суті сам по собі лок - це аналог критичної секції, synchronized-блоку. Цього в принципі може вистачити, але в простих випадках краще вже користуватись блоками synchronized. Основний профіт високорівневих локів - у використання їх як моніторів, і для цього потрібно створити одну чи кілька умовних змінних.  

Крім методів диктованих інтерфейсом Lock, у класі є методи для отримання інформацїї про стан локу (кількість входів, кількість потоків у чергах для кожної умовної змінної, блокуючий потік, чесність тощо).


Умовні змінні
Для створення умовних змінних призначений метод newCondition. Умовні змінні призначенні для координації потоків по певній умови - звідси й назва (англ. conditional variables), тому гарною практикою є вибір імені змінної, що прямо пов’язує її з відповідною умовою. Для прикладу у коді ArrayBlockingQueue (Oracle JDK 7), умовні змінні називаються notEmpty та notFull для сповіщення про стан, коли внутрішній буфер відповідно має об’єкт у черзі на читання та має вільне місце на прийом нових об’єктів   

/** Main lock guarding all access */
final ReentrantLock lock;
/** Condition for waiting takes */
private final Condition notEmpty;
/** Condition for waiting puts */
private final Condition notFull;

Умовні змінні таким чином інкапсулють певну умову, що використовуюється для координації потоків. ArrayBlockingQueue є прикладом повноцінного монітора Хоара.  


Умовні змнні (інтерфейс Condition) мають методи, що повинні вам бути знайомі: await() - аналог Object#wait(), signal() та signalAll() - аналоги Object#notify() та Object#notifyAll(), але на відміну від останніх signal() та signalAll() мають послаблені вимоги до стану лока - реалізація може не вимагати захоплення монітора. Однак внутрішня реалізація все таки вимгає, щоб визиваючий код містився у критичній секції.

Крім того є три аналоги Object#wait(long):
  • Condition#await(long, TimeUnit) - потік чекатиме синхронізації вказану кількість одиниць часу у TimeUnit’ах
  • Condition#awaitNanos(long) - потік чекатиме синхронізації вказаний час у наносекундах 
  • Сondition#awaitUntil(Date) - потік чекатиме синхронізації до вказаної дати
Три забагато, бо TimeUnit підтримує наносекунди.
TimeUnit - взагалі дуже зручний утилітний клас для роботи з одиницями часу навіть у звичайних програмах. Дозволяє уникати магічних часових констант типу 24, 60, 3600 (інші рахувати впадло). Натомість пропонується наступне:
package part2;

import java.util.concurrent.TimeUnit;

public class TimeUnitDemo {

    public static void main(String[] args) throws InterruptedException {
        // без TimeUnit
        Thread.sleep(10*24*3600*1000);
        
        // з TimeUnit
        Thread.sleep(TimeUnit.DAYS.toMillis(10));
        
        // ще краще ;)
        TimeUnit.DAYS.sleep(10);
    }
}


І справжнє полегшення, - метод Condition#awaitUninterruptibly() - дозволяє відкласти обробку переривання потоку - виклику Thread#interrupt(), - і виконати її після завершення цього методу. Решта методів негайно кидають InterruptedException.  Готувати так:
 
package part2;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class UninterruptiblyWaitForTheEnd {

    public static void main(String[] args) {
        final Lock lock = new ReentrantLock();
        final Condition doomsDay = lock.newCondition();

        // Запускаєм счьотчік
        new Thread(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                try {
                    TimeUnit.DAYS.sleep(10);
                    doomsDay.signal();
                } catch (InterruptedException e) {
                    // піздєц отмєняєтся по тєхніческім прічінам
                } finally {
                    lock.unlock();
                }
            }
        }).start();

        // Хоч від JVM взагалі нема гарантій, 
        // що до цього моменту 10 секунд не вийшло 
        // і не наступив піздєц,
        // ми - наївні пацани, - сподіваємось, що це не так
        boolean theEndHasCame;
        lock.lock();
        try {
            do {
                doomsDay.awaitUninterruptibly();

                if (theEndHasCame = hasTheEndCome()) {
                    // написати у Твіттер, що настав кінець світу
                    System.exit(0); // місію виконано
                }

                if (Thread.interrupted()) {
                    // далі йде обробка виклику interrupt() 
                    // з матюками у лог на тему яка у нас важлива місія
                }
            } while (!theEndHasCame);
        } finally {
            lock.unlock();
        }
    }

    public static boolean hasTheEndCome() {
        // На жаль http://www.doomsdayclock.org/ не має REST-інтерфейсу
        return true;
    }
}


Взагалі тут варто звернути увагу на те, що звільнення локу винесено в блок finally - це по-перше. По-друге, я не забув про spurious wakeups, по-третє - пам’ятайте що Thread#interrupted() скидує стан переривання потоку. 


Чи можна користуватись новим блоком try?
На жаль у JDK 7 локи не можуть бути використані як ресурси нового блоку try і автоматично звільнені не будуть. Можна це обійти, написавши невелику обгортку чи просто наслідувати ReentrantLock для підтримки AutoCloseable, але в питаннях паралельних я не бачу в цьому нічого хорошого. Робити так чи ні - вирішіть самі.

Три слова про чесність (fairness)
Остання важлива особливість локів - це можливість створювати їх відносно чесними. Конструктор ReentrantLock'а має необов'язковий параметр fairness. Грубо кажучи, чесні локи дозволяють вхід до критичної секції потокам в порядку викликів lock(), більш точно - завжди перевага надається потоку який довше чекає. Звичайні локи не дають таких гарантій і за рахунок цього вони трохи ефективніші. Відносно чесними такі локи є тому, що операційна система не зобов'язана чесно розподіляти процесор між потоками - це залежить від ОС та параметрів ядра. Непогане дослідження з цифрами можна знайти у статті The fairness of java.util.concurrent.locks.ReentrantLock

* * *

У мене все про локи та умовні змінні, хоч кілька цікавих методів не висвітлено. Загалом ReentrantLock повинен задовольнити будь-які питання роботи з довільними техніками синхронізації. На черзі семафори та ReadWriteLock.


До зустрічі!

пʼятниця, 26 серпня 2011 р.

2000 pageviews! Yikes!


It's fantastic, because i don't know who was 2000th, it might have been Yandex.
It's not much, but as lazy as I am, I didn't hoped to make this many. As happy as I am now I just felt I should write something about this.

Time to review stats!
It was quite some time since I have started this blog, less than a year, and I still have some crowd to be proud: http://mantonov.blogspot.com/ and http://arhipov.blogspot.com/. Thanks, I'll continue even if it's just for you two!

Also special thanks to http://javenue.info/ who was just the right guy to pass SCJP with!

It was a coincidence but a good timing to switch to new domain, which looks much more human than previous. I still haven't paid much attention to SEO and design since start so this is a good thing to do in the next year.

New part of java.util.concurrent is being prepared with me googling every tiny detail about why and how, stay tuned, but you may be disappointed as I started it in Ukrainian. That's a try and I plan to translate it to Russian once done. I wish I had an app that'd write as I talk with some acceptable rate of errors, if you know any - please give me a shout!

Also I'd be thankful to anybody who suggests a good idea of the study-friendly but realistic app to illustrate the concurrency concepts. I have some ideas, but yours may be more exciting!

I was excited to know that our Institut of Cybernetics has a research on Ukrainian language recognition: http://uasoiro.org.ua/home/ It's pretty scary but you can navigates through frames - it looks quite promising. I hope to contact them next week, maybe they will be kind enough to open-source it, so I could port it on Mac and make pretty

Thats's it, gratz everyone and don't routine yourself! Ever!