Jump to page: 1 2 3
Thread overview
July 30, 2013

Dil için hızlı bir hafıza yönetimi sınıfı oluşturmaya çalıştım ve aşağıdaki kod oldukça hızlı çalıştı ama bir sorun var memory.ptr burada değişiyor. Mümkün mertebe bu değişmeden hafızada yer ayırtma gibi bir şansımız var mı?

Veya Ali hocam, Salih hocam bu koda eklemeyi düşündüğünüz şeyler var mı?

module main;
import std.stdio;

import std.datetime;
import std.container;
import core.memory;

struct tll{
	int ll;
}
int main(string[] argv){
	auto lx = new MM();
	auto y = Clock.currTime();
	foreach(i; 0..1_000_000){
//		auto ly = new tll(4);
		lx.malloc(4_000);
	}
	auto y2 = Clock.currTime();
	writeln(y2-y);
	while(1){
	}
	return 0;
}
class MM{
	union parcala{
		char[] our_memory;
		size_t length;
	}
	parcala system;
	int memory_ptr;
	this(){
		system = parcala(new char[](1024));
	}
	final void* malloc(size_t sz){
		if(system.length < memory_ptr){
			//writeln(system.our_memory.ptr);
			system.our_memory.length += 1024 * 4;
		}

		void* mem = &system.our_memory[memory_ptr];
		memory_ptr+=sz;
		return mem;
	}
	final void free(){
	}
}

Zekeriya

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 30, 2013

Merhaba,

Öncelikle 'union''a ihtiyacın var mı? Çünkü bellek alanı olarak kullandığın devingen (dynamic) dizinin, zaten çift taraflı bir 'length' özelliği var. Üstelik bunu kullanmışsın ve bence bir yansımasını kullanmaya gerek yok. Ayrıca bir kaç püf noktası ile birlikte daha güvenli bir ortam oluşturabiliriz...

Aşağıda, yazdığın sınıfı tekrar kodladım ve önemli değişiklikleri numaralandırdım:

  1. İlk olarak '_ptr' ile bitirdiğin değişken bir işaretçi olmadığı için bunu daha anlamlı bir isme çevirdim. Ayrıca tıpkı onun gibi görev yapan ama konum bilgisi değil de belleğin güncel bilgisini tutan bir 'memSize' ekledim.

  2. Ayrıca eklediğim bu önemli değişken ise düzenleyici bir şey. Güvenlik için ve senin yazılımında gerekli olmayacaktır. Belleğin görüntüsünü ekrana yazarken 8'li diziler halinde yapıyorum. Bunun doğru bir şekilde yapılabilmesi için de tam olarak 8 veya katları olacak şekilde bir kural koymalıydım. Yani 65 byte'lık bir alan açmak istersen 64 byte'lık açacak; hepsi bu ve önemsiz. Tabi toString() işlevine ek güvenlik (8'den düşük kalan bellek bölgesi yazma) önlemini alırsan gereksiz de...:)

  3. Asıl önemli bölüm ise bu madde. Çünkü belleğin genişletilmesi gereken zaman, güncel belleğin boyutundan ('memSize') daha büyük bir bellek bölgesini ('freeLocated') gösterdiği zamandır. Dolayısıyla talep edilecek bellek alanı, artık var olan bellek alanını geçiyorsa bunun verilmeden (adresinin döndürülmeden) önce yapılması gerekir. Ayrıca basit bir 'scope'(exit) ile sonraki bellek bölgesini işaret edebiliriz. Bunun anlamı 'return' satırını işlettikten sonra çalış demek.

import std.conv, std.string, std.stdio;

class MEM {
 private:
   char[] memory;
   size_t freeLocated, memSize; //                      (1)

 public:
   immutable byteSize = 8; // bits...

 this(size_t minSize) {
   size_t isOverload = minSize % byteSize; //           (2)
   memory = new char[](minSize - isOverload);
   memSize = memory.length;
 }

 private void extendMem() {
    memory.length += memSize * 2;
    memSize = memory.length;
 }

 final void* malloc(size_t size) {
   // Zamanında genişlemesi için---v                    (3)
   if(memSize  < freeLocated + size) {
     extendMem();
   }
   scope(exit) freeLocated += size;
   return &memory[freeLocated];
 }

 void memLoadingTest(string data) @property {
   auto mem = malloc(data.length);
   foreach(i, chr; data) {
     *(cast(char*)mem + i) = chr;
   }
 }

 override string toString() const {
   import std.range : repeat;
   string memImage  = "       DECIMAL MEMORY DUMP        ASCII  \n";
          memImage ~= format("%s\n", repeat('-', memImage.length)) ;

   for(int i; i < memory.length; i += byteSize) {
     auto row = memory[i..i + byteSize];
     foreach(ubyte address; row) {
       if(address < 10) memImage ~= "   ";
       else if(address < 100) memImage ~= "  ";
       else if(address < 256) memImage ~= " ";
       memImage ~= to!string(address);
     }
     memImage ~= " " ~ row ~ "\n";
   }
   return memImage ~ format("%s>Total %s bytes<\n", repeat(' ', 10), memory.length);
 }
}

void main() {
 with(new MEM(16)) {
   // Nokta ekle ve genişlemeye şahit ol---v
   foreach(data; [ "Bu ", "bir ", "deneme..." ]) {
     memory.length.writeln;
     memLoadingTest(data);
     toString.writeln();
   }
 }
}

Başarılar...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 30, 2013

Salih hocam yazdığınız kod oldukça leziz teşekkür ederim :) Kodu görünce utancımdan yerin dibine girdim.

Alıntı:

>

Yani bir dilimle bir size_t aynı belleği paylaşıyorlar. Dilimlerin arka planda iki üyeli bir tür olduklarını bildiğimize göre (önce bir size_t, sonra bir veri göstergesi) parcala.length aslında our_memory.length'in aynısı oluyor.

Alıntı:

>

Öncelikle union'a ihtiyacın var mı? Çünkü bellek alanı olarak kullandığın devingen (dynamic) dizinin, zaten çift taraflı bir length özelliği var. Üstelik bunu kullanmışsın ve bence bir yansımasını kullanmaya gerek yok. Ayrıca bir kaç püf noktası ile birlikte daha güvenli bir ortam oluşturabiliriz...

Evet haklısınız ihtiyaç yok union ile erişmek hızlı olacaktır diye düşündüm ama yanılmışım.

Salih hocam bu yaptığınız ASCII çevirme olayı bana oldukça ilham verdi diyebilirim. Amacım bu MM sınıfını dilin memory si olarak kullanmaktı ama şuanda dile compile seçeneği eklemek için düşünüyorum.

Alıntı:

>

Bir hata görüyorum: Başlangıçta 1024 bayt yer olduğu halde ondan daha büyük bir istek gelse bile belleği uzatmadan o isteği karşılıyorsun.

Bildiğim kadarıyla object.length += 400 gibi bir ifade belleği uzatıyor.

Salih hocam kodda biraz değişiklik yaptım ve şöyle bir hale soktum.

module main;
import std.conv, std.string, std.stdio;

import std.container;
import core.memory;

int main(string[] argv){
	auto memory = new MEM(8);
	/*
	Her programın üstüne RhodeusScript imzasını çakmak hoş olur diye düşündüm.
	*/
	memory.memWrite("RhodeusScript");
	/*
	Burada dizi üzerinde int boyutunda bir yer açıp programımızın tanımlamalarının hangi offsetten başladığının bilgisini tutuyoruz.
	Örneğin string tanımlanmış bu stringin header kısmında önceden tanımlanmış olması gerekiyor
	*/
	auto defs = memory.memReserveAddress();
	/*
	Burada dizi üzerinde int boyutunda bir yer açıp programımızın hangi offsetten başladığının bilgisini tutuyoruz.
	*/
	auto program = memory.memReserveAddress();
	memory.memLoadString("0.0.1");//Version
	/*Definitions*/
	memory.memSetAddress(defs);
	memory.memLoadString("variable");
	/*Our Program*/
	memory.memSetAddress(defs);
	memory.memLoadBytes(cast(ubyte[]) [0x90, 0x90, 0x90, 0x90, 0xC3]);
	/*
	memLoadString gibi kısımlar artık birer hayal. Güzel bir sistem kurulabilir bunların saklanması için
	hem belkide bu esnada RhS nin nesne sistemi için güzel bir sistem kurgulanabilir
	*/
	memory.toString.writeln();
	while(1){
	}
	return 0;
}

class MEM {
private:
   ubyte[] memory;//varsayılan değerin 0xFF değil 0x00 olması gerektiğini fark ettim :)
   size_t freeLocated, memSize;

public:
   immutable byteSize = 8; // bits...

	this(size_t minSize) {
		size_t isOverload = minSize % byteSize;
		memory = new ubyte[](minSize - isOverload);
		memSize = memory.length;
	}

	private void extendMem() {
		memory.length += memSize * 2;
		memSize = memory.length;
	}
	final void memLoadBytes(inout ubyte[] data) @property {
		auto mem = cast(ubyte*) malloc(data.length);
		mem[0..data.length] = data;
	}
	final void* malloc(size_t size) {
		if(memSize  < freeLocated + size) {
			extendMem();
		}
		scope(exit) freeLocated += size;
		return &memory[freeLocated];
	}

	final void memWrite(inout(string) data) @property {//inout çünkü char[] de gelebilsin.
		auto mem = cast(char*) malloc(data.length);
		mem[0..data.length] = data;//Bunun daha hızlı olabileceğini düşündüm ama emin değilim.
/*		foreach(i, chr; data) {
			*(cast(char*)mem + i) = chr;
		}*/
	}
	final uint memReserveAddress() {
		/*
			Burada adres döndürmeyi çok isterdim ama memory.ptr sürekli olarak değişiyor.
			Bende dizi üzerindeki adresini döndürmeyi tercih ettim.
		*/
		scope(exit) malloc(int.sizeof);
		return freeLocated;
	}
	final void memSetAddress(uint adrl) {
		*cast(uint*) &memory[adrl] = memory.length;
	}
	void memLoadString(inout(string) data) @property {
		auto mem = cast(char*) malloc(data.length + ubyte.sizeof);
		*(cast(ubyte*)mem) = cast(ubyte) data.length;
		mem[ubyte.sizeof..data.length+ubyte.sizeof] = data;
	}

	override string toString() const{
		import std.range : repeat;
		string memImage  = "       DECIMAL MEMORY DUMP        ASCII  \n";
		memImage ~= format("%s\n", repeat('-', memImage.length)) ;

		for(int i; i < memory.length; i += byteSize) {
			auto row = memory[i..i + byteSize].dup;
			/*
			Çıktının doğru verilmesi için \0 görülen yeri 0xFF olarak değiştirdim.
			Bunun asıl veriyi etkilemesi ise sağlıksız olacaktır o yüzden dup kullandım.
			nasıl olsa toString sadece debug işlemimiz için olacak
			o halde dup edip hız kaybımız olması bizim için sorun olmaz
			*/
			foreach(ref ubyte address; row) {
				if(address == 0){
					address = 0xFF;
					memImage ~= " ";
				}else if(address < 10) memImage ~= "   ";
				else if(address < 100) memImage ~= "  ";
				else if(address < 256) memImage ~= " ";
				memImage ~= to!string(address);
			}
			memImage ~= " ";
			foreach(c; row){
				memImage ~= c;
			}
			memImage ~= "\n";
		}
		writeln(format("%s>Total %s bytes<\n", repeat(' ', 10), memory.length));
		return memImage ~ format("%s>Total %s bytes<\n", repeat(' ', 10), memory.length);
	}
}

Zekeriya

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 30, 2013

Alıntı (zekeriyadurmus):

>
> 	union parcala{
> 		char[] our_memory;
> 		size_t length;
> 	}
> ```


Yani bir dilimle bir size_t aynı belleği paylaşıyorlar. Dilimlerin arka planda iki üyeli bir tür olduklarını bildiğimize göre (önce bir size_t, sonra bir veri göstergesi) parcala.length aslında our_memory.length'in aynısı oluyor.

Alıntı:
>
>
  if(system.length < memory_ptr){
  	//writeln(system.our_memory.ptr);
  	system.our_memory.length += 1024 * 4;
  }

O zaman parcala.length üyesinden kurtulup system.our_memory.length yazamaz mısın?

Ek olarak, isimlerle ilgili iki gözlem:

  • memory_ptr bir gösterge gibi görünüyor ama aslında bir sayaç.

  • parcala gibi emir kipindeki isimler işlevlere ayrılsa daha iyi anlaşılır.

Bir hata görüyorum: Başlangıçta 1024 bayt yer olduğu halde ondan daha büyük bir istek gelse bile belleği uzatmadan o isteği karşılıyorsun.

Alıntı:

>

memory.ptr burada değişiyor. Mümkün mertebe bu değişmeden hafızada yer ayırtma gibi bir şansımız var mı?

Dilimler aşağıda anlatılan algoritmaya uygun olarak uzarlar; dilim kullandığın sürece yapacak bir şey yok:

http://ddili.org/makale/d_dilimleri.html

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 30, 2013

Alıntı (zekeriyadurmus):

>

Alıntı:

>

Bir hata görüyorum: Başlangıçta 1024 bayt yer olduğu halde ondan daha büyük bir istek gelse bile belleği uzatmadan o isteği karşılıyorsun.

Bildiğim kadarıyla object.length += 400 gibi bir ifade belleği uzatıyor.

Evet ama += işlemini önlüyorsun:

Alıntı:

>
>     final void* malloc(size_t sz){
>         if(system.length < memory_ptr){
>             //writeln(system.our_memory.ptr);
>             system.our_memory.length += 1024 * 4;
>         }
>
>         void* mem = &system.our_memory[memory_ptr];
>         memory_ptr+=sz;
>         return mem;
>     }
> ```


En başı düşünelim: system.length==1024 ve memory_ptr==0. Yani if bloğuna girilmez. O işlevin sz==1025 ile çağrıldığını düşün... 1024'lük alanın en başını 1025 yer isteyene vermiş olursun.

Ali

-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]
July 31, 2013

Haklısınız Ali hocam. Farketmemişim ama oldukça berbat bir kod zaten.

Zekeriya

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 31, 2013

Estağfirullah Zekeriyacığım...:)

Kimse anasının karnında kod yazmayı öğrenmedi. Gerçi bazılarımızda Allah vergisi bir yatkınlık oluyor. Ancak ne olursa olsun her geçen gün daha iyi kodlar yazıyorsun. Bu doğal bir süreç ve bu gayret etmekle ivme kazanacaktır. Bu gayret de sende olduğunu göre sadece biraz sabra ihtiyacın var.

Şimdi biz aslında, burada bir nevi devingen bir diziyi taklit ediyoruz. Bence gerçek bir manager (ben buna MEM yani, 'Memory Elastic Manager' diyorum) gerektiğinde kendini küçültebilmeli (kullanılmayan hafızayı serbest bırakmalı) ve bırakmayacaklarını da şekilden şekile sokup kullanabilmeli...

Şekilden kastım şu:

Bellek çıktısını hatırlıyorsun, üst bölüme '"bu bir deneme..."' yazdık ve sanırım 2 satırlık bir bölümü (belleği) işgal ediyordu. Gel zaman, git zaman (program koştuğu zaman) altına başka veriler eklendi. Ana, o da ne '(!)' ilk eklediğimiz veri artık kullanılmıyor. İşin ilginci tam da 16 byte'lık bir alana ihtiyaç var. Esnek yöneticimiz, bu duruma hemen ayak uydurup belleği genişletmek yerine artık kullanılmayan bu üst bölümün üzerine veri yazılabilir hakkı vermeli.

Maalesef an itibariyle biz bunu yapmak yerine, sınıra gelince diziyi genişletmeyi yeğliyoruz. Oysa D'nin bellek yöneticisi genişletme sırasında yeterli bellek olmadığı (capacity < reservedSize) zaman bütün verileri başka ve daha geniş bir alana taşımaya başlayacak...

Öyleyse bizim aynı anda 'memory.capacity' değişkenine bakarak bir genişletme eğilimine gitmemiz doğru olabilir. Bu son söylediğim senin şu soruna da ilaç olabilir:
Alıntı ("zekeriyadurmus"):

>

memory.ptr burada değişiyor. Mümkün mertebe bu değişmeden hafızada yer ayırtma gibi bir şansımız var mı?

Yani 'memory.capacity', istenilen bellekten (istenilen - var olan belleğin son bölümü) az ise belki bir şey yapamayız. Ama yetiyorsa tam da onun kadar genişletmemiz akıllıca olacaktır.

Başarılar...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 31, 2013

Allah razı olsun hocam sizlerden, çok şey öğrendim sayenizde.

Bu MEM i 2 farklı boyutta ilerletebiliriz diye düşünüyorum ki bence bu oldukça iş görecek.

  1. Derlenmiş rhs dosyası oluşturmak için bir mem sınıfı.
  2. Runtime esnada oluşturulan nesnelerin yönetimi için bir mem sınıfı.

Şu an için 1.sini yapmaya gerek yok ama ileride bir gün lazım olacağından dolayı köşede bir yerde durması iyi olur.

Gelelim 2.sine şu anda esas ihtiyacımız olan şey bu.

Hafıza yönetimi, çop toplama için çeşitli algoritmalar var belki önce bunları inceleyebiliriz.

Naïve mark-and-sweep, Tri-color marking, Dynamic memory allocation, Buddy memory allocation.

Bu algoritmaları az buçuk inceledim ama anlamam için biraz zaman gerekiyor. Şu anda dilin sınıf yapılarını oluşturuyorum bunları tamamladıktan sonra tekrar bu algoritmalara dönmeyi düşünüyorum.

Evet capacity kullanılabilir ama kafamı sürekli kurcalayan şey memory free yaptığımızda dizinin ilk başlarında ise bu veri ne olacağı.

Zekeriya

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 31, 2013

Bu forumdaki başlıklar, terimler ders niteliğinde :) Yeni bir dil yazmasam da yazacağım projelerde resmen ders :) Var olun hepiniz :)

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 31, 2013

Muhtemelen ben senden daha fazla bu konulara yabancıyımdır... ;-)

Bunları daha önce duymamıştım ve ilk olarak şu üç renk ile işaretleme yöntemi ilgimi çekti:

http://en.wikipedia.org/wiki/Garbage_collection_(computer_science)#Tri-color_marking

Wikipedia'ya bakılırsa en temel iki algoritmalardan biriymiş bu. Biraz okudum ve hoşuma gitti ama biz illa ki var olan teknikleri uygulayacağız diye bir şey yok. Tamam, bunları modelleyelim ama kendimizden de bir şey katalım. Sonuçta D'yi geliştirenler, literatürdeki bu algoritmaları çok daha iyi uygulayabilirler...:)

Biz atıyorum 3 değil, yapmışken 4 renk yapalım. Tamam, Amerika'yı tekrar keşfedelim demiyorum ama üretelim yahu. Hem böyle daha iyi öğreneceğimize eminim. Yoksa papağan ve maymunlar da çok güzel taklitler yaparlar. Bak hali hazırda geçen sene geliştirdiğim ve ilk olarak triBit (http://ddili.org/forum/thread/1030) olarak isimlendirdiğim sınıfı gönül rahatlığı ile kullanabilirsin. Gerçi bunun geliştirilmiş hali DNS Stack olarak mevcut. Bilmiyorum forumda paylaştım mı ama sana bir ara sdb/stacks.d modülünü verdiğimi hatırlıyorum. Onun içinde hepsi vardı.

Özetle, belleğe yerleştirilen verileri bahsettiğim sınıf ile pekala sınıflandırabiliriz. Ancak süpürme işlemini yapacak algoritma çok daha önemli. Yani tetikleme zamanı, şekli ve hıza etki edecek tüm faktörler.

Güzel şeyler bunlar...:)

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

« First   ‹ Prev
1 2 3