Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > e4xu

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

Manitu Group сделали интересную програмку - Azoth

Запись от wvxvw размещена 28.05.2010 в 01:14

Alchemy очень интересная штука, но для многих флешеров - скорее что-то из области научной фантастики. Кроме того, в обычной жизни ее так особо никто и не использует, кроме как всем извесный jpeg_encoder.
Что такое Azoth - это возможность использовать некоторые фишки Алхимии в обычных проектах.
Что он делает - заменяет вызовы к специальному классу специальными опкодами (командами виртуальной машины) для быстрого доступа к памяти.
Ниже приводится тест применения его на практике. Тестировались Адобовский Base64Encoder и мой на скорую руку написаный кодировщик Base64. Результат внушающий. Вариант обработанный Азотом оказался примерно в 6.5 раз быстрее фрейморковского. Хотя, я думаю, что если задаться целью соптимизировать еще больше, то можно еще улучшить показатели (можно было писать результат тоже в память вместо другуго ByteArray, но для теста / демонстрации и этого достаточно).
Итак, исходники и бенчмарки:
Код AS3:
package org.wvxvws.encoding.base64 
{
	import flash.utils.ByteArray;
	import flash.utils.Endian;
	import com.buraks.utils.fastmem;
 
	public class Base64 
	{
		private static const PAD:String = "=";
 
		/**
		 * ...
		 * @author wvxvw
		 */
		public function Base64() { super(); }
 
		public static function encode(bytes:ByteArray):String
		{
			var chunk:int;
			var readPosition:int = 64;
			var witePosition:int;
			var bytesLength:int = ((bytes.length * 0.3333333333333333) >>> 0) * 3 + 64;
			var tail:int = bytes.length + 64 - bytesLength;
			var ret:ByteArray = new ByteArray();
 
			ret.length = ((bytes.length * 0.3333333333333333) >>> 0) * 4;
 
			bytes.endian = Endian.LITTLE_ENDIAN;
			bytes.length += 64;
			bytes.position = 0;
			bytes.readBytes(bytes, 64);
			bytes.position = 0;
			bytes.writeMultiByte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "us-ascii");
			if (bytes.length < 1024) bytes.length = 1024;
 
			fastmem.fastSelectMem(bytes);
 
			while (readPosition < bytesLength)
			{
				chunk = fastmem.fastGetByte(readPosition++) << 16;
				chunk |= (fastmem.fastGetByte(readPosition++) << 8);
				chunk |= fastmem.fastGetByte(readPosition++);
 
				ret[witePosition++] = fastmem.fastGetByte(chunk >>> 18);
				ret[witePosition++] = fastmem.fastGetByte((chunk >>> 12) & 0x3F);
				ret[witePosition++] = fastmem.fastGetByte((chunk >>> 6) & 0x3F);
				ret[witePosition++] = fastmem.fastGetByte(chunk & 0x3F);
			}
			switch (tail)
			{
				case 1:
					chunk = fastmem.fastGetByte(readPosition++);
 
					ret[witePosition++] = fastmem.fastGetByte(chunk >>> 2);
					ret[witePosition++] = fastmem.fastGetByte((chunk & 3) << 4);
					ret[witePosition++] = 61;
					ret[witePosition++] = 61;
					break;
				case 2:
					chunk = fastmem.fastGetByte(readPosition++) << 8;
					chunk |= fastmem.fastGetByte(readPosition++);
 
					ret[witePosition++] = fastmem.fastGetByte(chunk >>> 10);
					ret[witePosition++] = fastmem.fastGetByte((chunk >>> 4) & 0x3F);
					ret[witePosition++] = fastmem.fastGetByte((chunk & 15) << 2);
					ret[witePosition++] = 61;
					break;
			}
			return ret.toString();
		}
	}
}
Код AS3:
package tests 
{
	import flash.display.Sprite;
	import flash.text.TextField;
	import flash.utils.ByteArray;
	import flash.utils.Endian;
	import flash.utils.getTimer;
	import org.wvxvws.encoding.base64.Base64;
	import mx.utils.Base64Encoder;
 
	/**
	 * ...
	 * @author wvxvw
	 */
	public class TestBase64 extends Sprite
	{
		[Embed(source='../../rsx/gray-lines.jpg', mimeType='application/octet-stream')]
		private var _binData:Class; // 444 Kb
 
		private var _field:TextField = new TextField();
 
		public function TestBase64() 
		{
			super();
			this._field.width = super.stage.stageWidth;
			this._field.height = super.stage.stageHeight;
			super.addChild(this._field);
			this.testFlex();
			this.testAzot();
		}
 
		/**
		 * Results for release player 10.0.45.2 standalone Windows XP SP3
		 * Run 0: 	Bytes encoded: 615197		time spent: 268
		 * Run 1: 	Bytes encoded: 615197		time spent: 258
		 * Run 2: 	Bytes encoded: 615197		time spent: 263
		 * Run 3: 	Bytes encoded: 615197		time spent: 285
		 * Run 4: 	Bytes encoded: 615197		time spent: 269
		 * Run 5: 	Bytes encoded: 615197		time spent: 261
		 * Run 6: 	Bytes encoded: 615197		time spent: 275
		 * Run 7: 	Bytes encoded: 615197		time spent: 256
		 * Run 8: 	Bytes encoded: 615197		time spent: 256
		 * Run 9: 	Bytes encoded: 615197		time spent: 276
		 * Run 10: 	Bytes encoded: 615197		time spent: 264
		 */
		private function testFlex():void
		{
			var encoder:Base64Encoder = new Base64Encoder();
			var ba:ByteArray = new _binData() as ByteArray;
			ba.endian = Endian.LITTLE_ENDIAN;
			var t:int = getTimer();
			encoder.encodeBytes(ba);
			var s:String = encoder.flush();
			t = getTimer() - t;
			this._field.appendText("\rFlex\rBytes encoded: " + s.length + "\rtime spent: " + t + "\r       ");
		}
 
		/**
		 * Results for release player 10.0.45.2 standalone Windows XP SP3
		 * Run 0: 	Bytes encoded: 607208		time spent: 40
		 * Run 1: 	Bytes encoded: 607208		time spent: 44
		 * Run 2: 	Bytes encoded: 607208		time spent: 39
		 * Run 3: 	Bytes encoded: 607208		time spent: 40
		 * Run 4: 	Bytes encoded: 607208		time spent: 39
		 * Run 5: 	Bytes encoded: 607208		time spent: 39
		 * Run 6: 	Bytes encoded: 607208		time spent: 41
		 * Run 7: 	Bytes encoded: 607208		time spent: 40
		 * Run 8: 	Bytes encoded: 607208		time spent: 40
		 * Run 9: 	Bytes encoded: 607208		time spent: 40
		 * Run 10: 	Bytes encoded: 607208		time spent: 40
		 */
		private function testAzot():void
		{
			var ba:ByteArray = new _binData() as ByteArray;
			ba.endian = Endian.LITTLE_ENDIAN;
			var t:int = getTimer();
			var s:String = Base64.encode(ba);
			t = getTimer() - t;
			this._field.appendText("\rAzot\rBytes encoded: " + s.length + "\rtime spent: " + t + "\r       ");
		}
	}
}
Некоторые примечания: Адобовский кодировщик добавляет возврат каретки, но это не является обязательным условием Base64, я не стал это добавлять, изза этого разница в длине результата.

Теперь, небольшое объяснение, как оно работает: По сути все очень просто, обращения к fastmem заменяются после обработки на соответствующие им опкоды, в чем можно легко убедится используя SWFDump утилиту из SDK. Ниже приводится участок кода который соответствует while циклу из Base64.encode(). Первый листинг - до обработки, второй - после. Обратите внимание на строчки с :fastGetByte (1), которые трансформируются в OP_0x35.
Код:
    L2: label         	
        getlex        	com.buraks.utils:fastmem
        getlocal3     	
        dup           	
        increment_i   	
        setlocal3     	
        callproperty  	:fastGetByte (1)
        pushbyte      	16
        lshift        	
        setlocal2     	
        getlocal2     	
        getlex        	com.buraks.utils:fastmem
        getlocal3     	
        dup           	
        increment_i   	
        setlocal3     	
        callproperty  	:fastGetByte (1)
        pushbyte      	8
        lshift        	
        bitor         	
        setlocal2     	
        getlocal2     	
        getlex        	com.buraks.utils:fastmem
        getlocal3     	
        dup           	
        increment_i   	
        setlocal3     	
        callproperty  	:fastGetByte (1)
        bitor         	
        setlocal2     	
        getlocal      	7
        getlocal      	4
        dup           	
        increment_i   	
        setlocal      	4
        dup           	
        setlocal      	8
        getlex        	com.buraks.utils:fastmem
        getlocal2     	
        pushbyte      	18
        urshift       	
        callproperty  	:fastGetByte (1)
        setproperty   	private,,private,org.wvxvws.encoding.base64,org.wvxvws.encoding.base64,http://adobe.com/AS3/2006/builtin,org.wvxvws.encoding.base64:Base64,org.wvxvws.encoding.base64:Base64,Object:null
        getlocal      	7
        getlocal      	4
        dup           	
        increment_i   	
        setlocal      	4
        dup           	
        setlocal      	9
        getlex        	com.buraks.utils:fastmem
        getlocal2     	
        pushbyte      	12
        urshift       	
        pushbyte      	63
        bitand        	
        callproperty  	:fastGetByte (1)
        setproperty   	private,,private,org.wvxvws.encoding.base64,org.wvxvws.encoding.base64,http://adobe.com/AS3/2006/builtin,org.wvxvws.encoding.base64:Base64,org.wvxvws.encoding.base64:Base64,Object:null
        getlocal      	7
        getlocal      	4
        dup           	
        increment_i   	
        setlocal      	4
        dup           	
        setlocal      	10
        getlex        	com.buraks.utils:fastmem
        getlocal2     	
        pushbyte      	6
        urshift       	
        pushbyte      	63
        bitand        	
        callproperty  	:fastGetByte (1)
        setproperty   	private,,private,org.wvxvws.encoding.base64,org.wvxvws.encoding.base64,http://adobe.com/AS3/2006/builtin,org.wvxvws.encoding.base64:Base64,org.wvxvws.encoding.base64:Base64,Object:null
        getlocal      	7
        getlocal      	4
        dup           	
        increment_i   	
        setlocal      	4
        dup           	
        setlocal      	11
        getlex        	com.buraks.utils:fastmem
        getlocal2     	
        pushbyte      	63
        bitand        	
        callproperty  	:fastGetByte (1)
        setproperty   	private,,private,org.wvxvws.encoding.base64,org.wvxvws.encoding.base64,http://adobe.com/AS3/2006/builtin,org.wvxvws.encoding.base64:Base64,org.wvxvws.encoding.base64:Base64,Object:null
        kill          	11
        kill          	10
        kill          	9
        kill          	8
Код:
    L2: label         	
        nop           	
        getlocal3     	
        dup           	
        increment_i   	
        setlocal3     	
        OP_0x35       	
        pushbyte      	16
        lshift        	
        setlocal2     	
        getlocal2     	
        nop           	
        getlocal3     	
        dup           	
        increment_i   	
        setlocal3     	
        OP_0x35       	
        pushbyte      	8
        lshift        	
        bitor         	
        setlocal2     	
        getlocal2     	
        nop           	
        getlocal3     	
        dup           	
        increment_i   	
        setlocal3     	
        OP_0x35       	
        bitor         	
        setlocal2     	
        getlocal      	7
        getlocal      	4
        dup           	
        increment_i   	
        setlocal      	4
        dup           	
        setlocal      	8
        nop           	
        getlocal2     	
        pushbyte      	18
        urshift       	
        OP_0x35       	
        setproperty   	private,,private,org.wvxvws.encoding.base64,org.wvxvws.encoding.base64,http://adobe.com/AS3/2006/builtin,org.wvxvws.encoding.base64:Base64,org.wvxvws.encoding.base64:Base64,Object:null
        getlocal      	7
        getlocal      	4
        dup           	
        increment_i   	
        setlocal      	4
        dup           	
        setlocal      	9
        nop           	
        getlocal2     	
        pushbyte      	12
        urshift       	
        pushbyte      	63
        bitand        	
        OP_0x35       	
        setproperty   	private,,private,org.wvxvws.encoding.base64,org.wvxvws.encoding.base64,http://adobe.com/AS3/2006/builtin,org.wvxvws.encoding.base64:Base64,org.wvxvws.encoding.base64:Base64,Object:null
        getlocal      	7
        getlocal      	4
        dup           	
        increment_i   	
        setlocal      	4
        dup           	
        setlocal      	10
        nop           	
        getlocal2     	
        pushbyte      	6
        urshift       	
        pushbyte      	63
        bitand        	
        OP_0x35       	
        setproperty   	private,,private,org.wvxvws.encoding.base64,org.wvxvws.encoding.base64,http://adobe.com/AS3/2006/builtin,org.wvxvws.encoding.base64:Base64,org.wvxvws.encoding.base64:Base64,Object:null
        getlocal      	7
        getlocal      	4
        dup           	
        increment_i   	
        setlocal      	4
        dup           	
        setlocal      	11
        nop           	
        getlocal2     	
        pushbyte      	63
        bitand        	
        OP_0x35       	
        setproperty   	private,,private,org.wvxvws.encoding.base64,org.wvxvws.encoding.base64,http://adobe.com/AS3/2006/builtin,org.wvxvws.encoding.base64:Base64,org.wvxvws.encoding.base64:Base64,Object:null
        kill          	11
        kill          	10
        kill          	9
        kill          	8
Всего комментариев 4

Комментарии

Старый 28.05.2010 03:10 wvxvw вне форума
wvxvw
 
Аватар для wvxvw
Интересный момент. Попробовал "соптимизировать" вот так:
Код AS3:
package org.wvxvws.encoding.base64 
{
	import flash.utils.ByteArray;
	import flash.utils.Endian;
	import com.buraks.utils.fastmem;
 
	public class Base64 
	{
		/**
		 * ...
		 * @author wvxvw
		 */
		public function Base64() { super(); }
 
		public static function encode(bytes:ByteArray):String
		{
			var chunk:int;
			var readPosition:int = 64;
			var witePosition:int;
			var bytesLength:int = ((bytes.length * 0.3333333333333333) >>> 0) * 3 + 64;
			var tail:int = bytes.length + 64 - bytesLength;
			var ret:ByteArray = new ByteArray();
 
			ret.length = ((bytes.length * 0.3333333333333333) >>> 0) * 4;
 
			bytes.endian = Endian.LITTLE_ENDIAN;
			bytes.length += 64;
			bytes.position = 0;
			bytes.readBytes(bytes, 64);
			bytes.position = 0;
			bytes.writeMultiByte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "us-ascii");
			if (bytes.length < 1024) bytes.length = 1024;
 
			fastmem.fastSelectMem(bytes);
 
			while (readPosition < bytesLength)
			{
				chunk = fastmem.fastGetByte(readPosition++) << 16;
				chunk |= (fastmem.fastGetByte(readPosition++) << 8);
				chunk |= fastmem.fastGetByte(readPosition++);
 
				ret.writeUnsignedInt(
					(fastmem.fastGetByte(chunk >>> 18) << 24) |
					(fastmem.fastGetByte((chunk >>> 12) & 0x3F) << 16) |
					(fastmem.fastGetByte((chunk >>> 6) & 0x3F) << 8) |
					fastmem.fastGetByte(chunk & 0x3F)
				);
			}
			switch (tail)
			{
				case 1:
					chunk = fastmem.fastGetByte(readPosition++);
 
					ret.writeUnsignedInt(
						(fastmem.fastGetByte(chunk >>> 2) << 24) |
						(fastmem.fastGetByte((chunk & 3) << 4) << 16) |
						15677
					);
					break;
				case 2:
					chunk = fastmem.fastGetByte(readPosition++) << 8;
					chunk |= fastmem.fastGetByte(readPosition++);
 
					ret.writeUnsignedInt(
						(fastmem.fastGetByte(chunk >>> 10) << 24) |
						(fastmem.fastGetByte((chunk >>> 4) & 0x3F) << 16) |
						(fastmem.fastGetByte((chunk & 15) << 2) << 8) | 61
					);
					break;
			}
			ret.position = 0;
			return ret.readUTFBytes(ret.length);
		}
	}
}
Но ни на что не повлияло Даже возможно, стало чуть медленнее.

Ну и раз уж пошло такое дело, решил попробовать в HaXe:
Код AS3:
/**
 * ...
 * @author wvxvw
 */
 
package org.wvxvws.encoding;
import haxe.io.Bytes;
import haxe.Timer;
 
class Base64 
{
	public function new() { }
 
	public static function encode(input:Bytes):String
	{
		var chunk:Int;
		var readPosition:Int = 64;
		var witePosition:Int = 0;
		var bytes:Bytes = Bytes.alloc(input.length + 64);
		var bytesLength:Int = Std.int(bytes.length * 0.3333333333333333) * 3 + 64;
		var tail:Int = bytes.length + 64 - bytesLength;
		var ret:Bytes = Bytes.alloc(Std.int(bytes.length * 0.3333333333333333) * 4);
 
		bytes.blit(0, Bytes.ofString("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"), 0, 64);
		bytes.blit(64, input, 0, input.length);
 
		while (readPosition < bytesLength)
		{
			chunk = bytes.get(readPosition++) << 16;
			chunk |= (bytes.get(readPosition++) << 8);
			chunk |= bytes.get(readPosition++);
 
			ret.set(witePosition++, bytes.get(chunk >>> 18));
			ret.set(witePosition++, bytes.get((chunk >>> 12) & 0x3F));
			ret.set(witePosition++, bytes.get((chunk >>> 6) & 0x3F));
			ret.set(witePosition++, bytes.get(chunk & 0x3F));
		}
		switch (tail)
		{
			case 1:
				chunk = bytes.get(readPosition++);
 
				ret.set(witePosition++, bytes.get(chunk >>> 2));
				ret.set(witePosition++, bytes.get((chunk & 3) << 4));
				ret.set(witePosition++, 61);
				ret.set(witePosition++, 61);
			case 2:
				chunk = bytes.get(readPosition++) << 8;
				chunk |= bytes.get(readPosition++);
 
				ret.set(witePosition++, bytes.get(chunk >>> 10));
				ret.set(witePosition++, bytes.get((chunk >>> 4) & 0x3F));
				ret.set(witePosition++, bytes.get((chunk & 15) << 2));
				ret.set(witePosition++, 61);
		}
		return ret.readString(0, ret.length);
	}
}
Код AS3:
/**
 * ...
 * @author wvxvw
 */
package tests;
import flash.Lib;
import flash.text.TextField;
import haxe.io.Bytes;
import haxe.io.BytesData;
import org.wvxvws.encoding.Base64;
 
class TestBase64 
{
	public function new() { }
 
	public static function main()
	{
		var tf:TextField = new TextField();
		tf.width = Lib.current.stage.stageWidth;
		tf.height = Lib.current.stage.stageHeight;
		Lib.current.addChild(tf);
		var bd:BytesData = new BytesData();
		bd.writeBytes(new GraylinesImage());
		var ba:Bytes = Bytes.ofData(bd);
		var t:Int = Lib.getTimer();
		var s:String = Base64.encode(ba);
		t = Lib.getTimer() - t;
		tf.text = "HaXe Bytes encoded: " + s.length + "\ttime spent: " + t;
	}
}
import flash.utils.ByteArray;
 
class GraylinesImage extends ByteArray
{
	public function new() { super(); }
}
Код:
<shx:resources version="9" compress="false" package="tests"
	xmlns:shx="http://mindless-labs.com/samhaxe"
	xmlns:bin="http://mindless-labs.com/samhaxe/modules/Binary"
	xmlns:comp="http://mindless-labs.com/samhaxe/modules/Compose"
	xmlns:font="http://mindless-labs.com/samhaxe/modules/Font"
	xmlns:img="http://mindless-labs.com/samhaxe/modules/Image"
	xmlns:snd="http://mindless-labs.com/samhaxe/modules/Sound"
	xmlns:swf="http://mindless-labs.com/samhaxe/modules/Swf"
	>

	<shx:frame>
		<bin:binary import="gray-lines.jpg" class="GraylinesImage"/>
	</shx:frame>

</shx:resources>
Результат такой же, как с Азотом
Обновил(-а) wvxvw 28.05.2010 в 04:37
Старый 03.06.2010 20:37 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
а ты пробовал заменить
Код AS3:
fastmem.fastGetByte( value )
заменить на
Код AS3:
bytes[ value ]
Старый 03.06.2010 21:19 wvxvw вне форума
wvxvw
 
Аватар для wvxvw
Пробовал, примерно в 2 раза медленнее.
Старый 04.06.2010 14:30 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
аке =) спасибо
 

 


Часовой пояс GMT +4, время: 12:10.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.