[c#] remoting + memory gebruik

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • justice strike
  • Registratie: Juni 2001
  • Laatst online: 08-08 09:26
Ik zit met een probleem waarvan ik zelf niet begrijp waarom dit zich voorkomt.

Ik heb een remotingservice die een object aanbied als well known singleton:

code:
1
2
3
TcpChannel channel = new TcpChannel(10501);
            ChannelServices.RegisterChannel(channel, false);
            RemotingConfiguration.RegisterWellKnownServiceType(typeof(DoubleArray), "DoubleArray", WellKnownObjectMode.Singleton);


het object aanroepen doe ik met:

code:
1
q = (DoubleArray)Activator.GetObject(typeof(DoubleArray), "tcp://localhost:10501/DoubleArray", WellKnownObjectMode.Singleton);


nu is de double array 160 mb. Opzich geen probleem als het maar een singleton blijft. Maar wat ik merk is dat hij voor elke referentie 160 mb reserveert, waardoor ik je redelijk snel tegen de max aanloopt en hij een outofmemory exception geeft.

het zijn overigens MarshalByRefComponent dus het object wordt net eens verplaatst naar de client. (MarshalByValueComponent geven weer andere problemen)

ik begrijp nog steeds niet waarom hij voor elke connectie een extra object maakt (of geheugen reserveert) en waarom hij bij het sluiten van de connectie dat geheugen niet weer vrijgeeft. Iemand enig idee?

U can call me sir.... or justice as long as u bow down ;)


Acties:
  • 0 Henk 'm!

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Waarom is DoubleArray 160MB? Alloceert hij dat in de ctor?

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Acties:
  • 0 Henk 'm!

  • justice strike
  • Registratie: Juni 2001
  • Laatst online: 08-08 09:26
EfBe schreef op donderdag 23 oktober 2008 @ 12:12:
Waarom is DoubleArray 160MB? Alloceert hij dat in de ctor?
160 mb is om de datahoeveelheid te simuleren. Er moet ongeveer 160 mb aan data verschoven worden en ja dat wordt in de ctor gealloceert

U can call me sir.... or justice as long as u bow down ;)


Acties:
  • 0 Henk 'm!

  • Haan
  • Registratie: Februari 2004
  • Laatst online: 20:53

Haan

dotnetter

Zou static maken kunnen helpen? (als dat uberhaupt kan in deze situatie, ik ken deze constructie niet :+ )

Kater? Eerst water, de rest komt later


Acties:
  • 0 Henk 'm!

  • justice strike
  • Registratie: Juni 2001
  • Laatst online: 08-08 09:26
Geprobeert maar werkt niet. Maargoed vraag blijft, het is een singleton. Daar hoort maar 1 active object van te zijn. Waarmo vreet het dan resources.

[ Voor 8% gewijzigd door justice strike op 23-10-2008 12:48 ]

U can call me sir.... or justice as long as u bow down ;)


Acties:
  • 0 Henk 'm!

  • bigbeng
  • Registratie: Augustus 2000
  • Laatst online: 26-11-2021
Ik zou eerst proberen te achterhalen waar de allocatie plaatsvindt. Dus eerst bepalen of de aanroep van de constructor daadwerkelijk maar 1x gebeurt, controleren of het geheugengebruik op de client of op de server wordt gealloceerd, dat soort dingen.

In het remoting voorbeeld dat ik van http://csharptuning.blogs.../09/remoting-in-c_05.html heb gehaald heb ik in het remoting object een array opgenomen van 20.000.000 integers, dus grofweg 80Mb in geheugengebruik. Als ik de System.GC.GetTotalMemory() afdruk op de server, dan zie ik het geheugengebruik wel toenemen, maar niet met veel meer dan een paar Kb per call.
Het aanmaken van het object gebeurt in elk geval maar 1x, dus hij houdt zich netjes aan het Singleton principe. Wat dan wel weer interessant is, is het feit dat de client ook 80Mb gebruikt als ik de variabele static maak. Dit lijkt eerder een negatief dan een positief effect te hebben.

Dus mogelijk is er toch iets mis in jouw configuratie, want bij mij lijkt het zich redelijk conform verwachtingen te gedragen.

Acties:
  • 0 Henk 'm!

  • justice strike
  • Registratie: Juni 2001
  • Laatst online: 08-08 09:26
bij mij lijtk hij zich echt als sincle call obbject te gedragen. Het geheugengebruik neemt gewoon toe met de object size naarmate er meer calls zijn. en neemt weer af als het object gedumpt wordt. Dus echt vreemd. Ik hoef toch alleen bij het registeren aan te geven dat het een singleton is of moet ik dat ergens anders ook doen (zie eerste post)

U can call me sir.... or justice as long as u bow down ;)


Acties:
  • 0 Henk 'm!

  • bigbeng
  • Registratie: Augustus 2000
  • Laatst online: 26-11-2021
Wie dumpt het object dan? Want bij mijn versie dump ik wel de client, maar het object op de server blijft bestaan. Bij een nieuwe aanroep naar de server wordt er geen nieuw object aangemaakt, maar blijft de oude behouden. Post anders eens wat code van het remoting object, misschien dat we daar iets aan kunnen zien.

Acties:
  • 0 Henk 'm!

  • justice strike
  • Registratie: Juni 2001
  • Laatst online: 08-08 09:26
server code:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void run()
        {
            TcpChannel channel = new TcpChannel(10501);
            RemotingConfiguration.RegisterWellKnownServiceType(typeof(DoubleArray), "DoubleArray", WellKnownObjectMode.Singleton);
           
            while(true)
            {
                Console.WriteLine(GC.GetTotalMemory(true));
                GC.Collect();
                Thread.Sleep(1000);
            }
            
            System.Console.WriteLine("Press the enter key to exit...");
            System.Console.ReadLine();
            return; // 0;
        }


client code:

code:
1
2
3
4
5
 q = (DoubleArray)Activator.GetObject(typeof(DoubleArray), "tcp://localhost:10501/DoubleArray");
            ILease le = (ILease)q.GetLifetimeService();
            Console.WriteLine("Current TTL: {0}", le.CurrentLeaseTime);
a = q.getDouble();
q = null


object:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    [Serializable()]
    public class DoubleArray : MarshalByRefObject
    {
        static byte[] a;

     
    
     public DoubleArray()
     {
         a = new byte[160000000];
         }

    public byte[] getDouble()
    {
    return a;
    }   
    }

U can call me sir.... or justice as long as u bow down ;)


Acties:
  • 0 Henk 'm!

  • EfBe
  • Registratie: Januari 2000
  • Niet online
justice strike schreef op donderdag 23 oktober 2008 @ 12:26:
[...]
160 mb is om de datahoeveelheid te simuleren. Er moet ongeveer 160 mb aan data verschoven worden en ja dat wordt in de ctor gealloceert
Waar wordt die 160MB telkens erbij gealloceerd? In de service of op de client? Hoe heb je je singleton gedefinieerd?

Omdat remoting een copy maakt van de data over de wire (behalve wanneer het object een proxy is) is meerdere keren aanroepen dus wel degelijk de oorzaak dat je meerdere keren 160MB op de client krijgt.

Overigens is je remoting call code wat raar. Waarom heb je geen service gedefinieerd en roep je die aan via een ander process? Nu zit je (zo lijkt het) in hetzelfde process client en service te spelen. Immers voor een remoting call hoef je geen Activator te gebruiken, maar creeer je eerst de service en roep je dan je method aan die de data teruggeeft.

[ Voor 23% gewijzigd door EfBe op 23-10-2008 16:43 ]

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Acties:
  • 0 Henk 'm!

  • justice strike
  • Registratie: Juni 2001
  • Laatst online: 08-08 09:26
EfBe schreef op donderdag 23 oktober 2008 @ 16:41:
[...]

Waar wordt die 160MB telkens erbij gealloceerd? In de service of op de client? Hoe heb je je singleton gedefinieerd?
bij de server
Omdat remoting een copy maakt van de data over de wire (behalve wanneer het object een proxy is) is meerdere keren aanroepen dus wel degelijk de oorzaak dat je meerdere keren 160MB op de client krijgt.
het is een proxy. de class is namelijk gedefinieerd als MarshalByRefObject (dus een referentie dus een proxy). Dat hij de data moet coderen en versturen dat begrijp ik. Maar dan zou ik pieken en dalen moeten zien bij de aanroep. Ik zie echter de geheuge allocatie alleen maar stijgen.
Overigens is je remoting call code wat raar. Waarom heb je geen service gedefinieerd en roep je die aan via een ander process? Nu zit je (zo lijkt het) in hetzelfde process client en service te spelen. Immers voor een remoting call hoef je geen Activator te gebruiken, maar creeer je eerst de service en roep je dan je method aan die de data teruggeeft.
met activator can ik een proxy krijgen van het object dat ik wil gebruiken. dat daar localhost staat wil niet zeggen dat het hetzelfde process is. dat is een ander programma wat op dezelfde computer zit. Maar op een andere pc krijg je hetzelfde probleem (dus echt remote object reference)

[ Voor 8% gewijzigd door justice strike op 23-10-2008 16:48 ]

U can call me sir.... or justice as long as u bow down ;)


Acties:
  • 0 Henk 'm!

  • bigbeng
  • Registratie: Augustus 2000
  • Laatst online: 26-11-2021
Volgens mij hoef je echt niet de Activator te gebruiken, je kunt ook gewoon client side het type registreren:
C#:
1
RemotingConfiguration.RegisterWellKnownClientType(typeof(DoubleArray), "tcp://localhost:10501/DoubleArray");

Ik ben niet voldoende thuis in de materie om te zeggen of jouw manier van aanroepen een andere memory footprint zou genereren.
Wat ik wel vermoed, maar niet zeker weet, is door de aanroep:
a = q.getDouble();
een lokale kopie maakt van je remote byte array, hij is immers niet als een remotable object gedefinieerd. Op die manier verdubbel je wel het verbruikte geheugen op de pc, omdat je nu lokaal aan het werk bent. Als je nog een client erbij opstart, krijgt die ook weer een kopie toegewezen. Denk ik in elk geval.
justice strike schreef op donderdag 23 oktober 2008 @ 16:46:
*snip*
Maar op een andere pc krijg je hetzelfde probleem (dus echt remote object reference)
Heb je dat ook getest, of is dat een vermoeden?

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 01:56
bigbeng schreef op donderdag 23 oktober 2008 @ 19:55:
Volgens mij hoef je echt niet de Activator te gebruiken, je kunt ook gewoon client side het type registreren:
C#:
1
RemotingConfiguration.RegisterWellKnownClientType(typeof(DoubleArray), "tcp://localhost:10501/DoubleArray");

Ik ben niet voldoende thuis in de materie om te zeggen of jouw manier van aanroepen een andere memory footprint zou genereren.
Als het al kan, zou het niet mogen.
Echter, ik vermoed dat, als je het doet mbhv de code die jij hier post (en dan mbhv de new operator een nieuw remote object instantieert), dat je dan een client activated remote component krijgt ipv een server activated
Wat ik wel vermoed, maar niet zeker weet, is door de aanroep:
a = q.getDouble();
een lokale kopie maakt van je remote byte array, hij is immers niet als een remotable object gedefinieerd.
De array zal geserializeerd worden, zodanig dat hij op de client beschikbaar is.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 01:56
justice strike schreef op donderdag 23 oktober 2008 @ 11:34:
nu is de double array 160 mb. Opzich geen probleem als het maar een singleton blijft. Maar wat ik merk is dat hij voor elke referentie 160 mb reserveert, waardoor ik je redelijk snel tegen de max aanloopt en hij een outofmemory exception geeft.
Hoe merk je dat ? Wat gebruik je om dit na te gaan ?

Wat bigbeng hier eerder zei, zou wel eens de nagel op de kop kunnen zijn ...

Kan je eens debuggen en zien hoeveel x de constructor van je remote object aangeroepen wordt ? (Hou ook rekening met de lifetime van je remote object).

Waarom erft je DoubleArray class trouwens over van MarshalByRefObject ? Dat hoeft helemaal niet ...

[ Voor 7% gewijzigd door whoami op 23-10-2008 21:00 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • justice strike
  • Registratie: Juni 2001
  • Laatst online: 08-08 09:26
bigbeng schreef op donderdag 23 oktober 2008 @ 19:55:
Volgens mij hoef je echt niet de Activator te gebruiken, je kunt ook gewoon client side het type registreren:
C#:
1
RemotingConfiguration.RegisterWellKnownClientType(typeof(DoubleArray), "tcp://localhost:10501/DoubleArray");

Ik ben niet voldoende thuis in de materie om te zeggen of jouw manier van aanroepen een andere memory footprint zou genereren.
ik ga hier nog even naar kijken. Volgens mij moet je namelijk toch ergens het object vandaan halen. Als je gewoon een double array aanmaakt dan kan hij lokaal dus ook eentje aanmaken en heb je een ander object (en dus geen singleton meer)
Wat ik wel vermoed, maar niet zeker weet, is door de aanroep:
a = q.getDouble();
een lokale kopie maakt van je remote byte array, hij is immers niet als een remotable object gedefinieerd. Op die manier verdubbel je wel het verbruikte geheugen op de pc, omdat je nu lokaal aan het werk bent. Als je nog een client erbij opstart, krijgt die ook weer een kopie toegewezen. Denk ik in elk geval.
lokaal geheugentoename vind ik niet erg. Ik wil alleen niet dat de server met 14 connecties ook 14 kopieen gaat bijhouden
Heb je dat ook getest, of is dat een vermoeden?
getest

U can call me sir.... or justice as long as u bow down ;)


Acties:
  • 0 Henk 'm!

  • justice strike
  • Registratie: Juni 2001
  • Laatst online: 08-08 09:26
whoami schreef op donderdag 23 oktober 2008 @ 20:10:
[...]
Hoe merk je dat ? Wat gebruik je om dit na te gaan ?
taskmanager maar ook de gc geeft info over het geheugenverbrijk van het programma
Wat bigbeng hier eerder zei, zou wel eens de nagel op de kop kunnen zijn ...

Kan je eens debuggen en zien hoeveel x de constructor van je remote object aangeroepen wordt ? (Hou ook rekening met de lifetime van je remote object).
ga ik even naar kijken.
Waarom erft je DoubleArray class trouwens over van MarshalByRefObject ? Dat hoeft helemaal niet ...
ik heb het anders niet werkend gekregen zonder. Je moet namelijk een proxy maken en dat regelt het MarshalByRefObject. Enige andere optie is MarshalByValueComponent, maar dat brengt weer andere problemen met zich mee. Hoe dan ook, als je met remoting werkt moet je een van de 2 gebruiken.

U can call me sir.... or justice as long as u bow down ;)


Acties:
  • 0 Henk 'm!

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

probeer eens
C#:
1
static byte[] a = new byte[160000000];

Daarnaast zal elke call naar getDouble() een kopie maken van de bytes aangezien die value-types zijn.

ASSUME makes an ASS out of U and ME


Acties:
  • 0 Henk 'm!

  • EfBe
  • Registratie: Januari 2000
  • Niet online
H!GHGuY schreef op vrijdag 24 oktober 2008 @ 08:31:
probeer eens
C#:
1
static byte[] a = new byte[160000000];

Daarnaast zal elke call naar getDouble() een kopie maken van de bytes aangezien die value-types zijn.
Dit is inderdaad denk ik wat er mis is, want de singleton definitie is niet correct:
je moet een static class en een static array gebruiken, en in de member definition de allocatie doen zodat je thread safe bent.

Deze code namelijk:
code:
1
2
3
4
5
 q = (DoubleArray)Activator.GetObject(typeof(DoubleArray), "tcp://localhost:10501/DoubleArray");
            ILease le = (ILease)q.GetLifetimeService();
            Console.WriteLine("Current TTL: {0}", le.CurrentLeaseTime);
a = q.getDouble();
q = null

doet:
- op de service een DoubleArray aanmaken (want marshallbyref)
- proxy data returnen naar client
- getDouble() wordt aangeroepen op proxy, call wordt gemarshalled naar service, daar wordt de data gereturned.

Volgende call: zelfde liedje, weer allocatie.

Wat de TS dus moet doen is niet Activator.GetObject gebruiken, maar een service definieren die een GetDouble() method heeft, en DIE method returned de static instance in de singleton.

[ Voor 42% gewijzigd door EfBe op 24-10-2008 09:40 ]

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 01:56
justice strike schreef op vrijdag 24 oktober 2008 @ 07:51:
[...]

taskmanager maar ook de gc geeft info over het geheugenverbrijk van het programma


[...]

ga ik even naar kijken.


[...]

ik heb het anders niet werkend gekregen zonder. Je moet namelijk een proxy maken en dat regelt het MarshalByRefObject. Enige andere optie is MarshalByValueComponent, maar dat brengt weer andere problemen met zich mee. Hoe dan ook, als je met remoting werkt moet je een van de 2 gebruiken.
DoubleArray is toch niet de component die remote gehost wordt, maar het resultaat dat je remote component verstuurt, of heb ik het mis ?
En is DoubleArray idd het remote component ? (Dan moet het nl. idd overerven van MarshalByRefObject).

edit:
Ok, nog eens gekeken: DoubleArray is idd je component dat remote gehost wordt.

[ Voor 5% gewijzigd door whoami op 24-10-2008 09:42 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 01:56
EfBe schreef op vrijdag 24 oktober 2008 @ 09:37:
[...]

code:
1
2
3
4
5
 q = (DoubleArray)Activator.GetObject(typeof(DoubleArray), "tcp://localhost:10501/DoubleArray");
            ILease le = (ILease)q.GetLifetimeService();
            Console.WriteLine("Current TTL: {0}", le.CurrentLeaseTime);
a = q.getDouble();
q = null

doet:
- op de service een DoubleArray aanmaken (want marshallbyref)
- proxy data returnen naar client
- getDouble() wordt aangeroepen op proxy, call wordt gemarshalled naar service, daar wordt de data gereturned.

Volgende call: zelfde liedje, weer allocatie.
Idd.
Op de server bestaat er maar één instantie van DoubleArray, maar bij iedere call naar GetDouble() wordt er een nieuwe array gealloceerd.
Wat de TS dus moet doen is niet Activator.GetObject gebruiken, maar een service definieren die een GetDouble() method heeft, en DIE method returned de static instance in de singleton.
Ik ben het eens met het 2de gedeelte van die zin, maar waarom zou hij niet Activator.GetObject moeten gebruiken ? Als dit een remote service is, zie ik niet in hoe hij anders een (server activated) remote component kan gaan aanroepen ...

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • justice strike
  • Registratie: Juni 2001
  • Laatst online: 08-08 09:26
EfBe schreef op vrijdag 24 oktober 2008 @ 09:37:
[...]

Dit is inderdaad denk ik wat er mis is, want de singleton definitie is niet correct:
je moet een static class en een static array gebruiken, en in de member definition de allocatie doen zodat je thread safe bent.
het feit dat je een afgeleide van MarshalByRefObject aan het maken bent zorgt er al voor dat je thread safe bent. En als ik de library mag geloven zorgt de register service ervoor dat het object een singleton is (en blijft) zodat je dat nergens anders hoeft te definieren. Dit is zo gedaan omdat je wellicht gewone objecten wil kunnen gebruiken als singleton zonder dat je deze expliciet hoeft te definieren.

Ik ga echter even kijken of dit werkt.
Deze code namelijk:
code:
1
2
3
4
5
 q = (DoubleArray)Activator.GetObject(typeof(DoubleArray), "tcp://localhost:10501/DoubleArray");
            ILease le = (ILease)q.GetLifetimeService();
            Console.WriteLine("Current TTL: {0}", le.CurrentLeaseTime);
a = q.getDouble();
q = null

doet:
- op de service een DoubleArray aanmaken (want marshallbyref)
- proxy data returnen naar client
- getDouble() wordt aangeroepen op proxy, call wordt gemarshalled naar service, daar wordt de data gereturned.

Volgende call: zelfde liedje, weer allocatie.
ja dat doet hij, als er geen DoubleArray is aangemaakt (eerste aanroep)
als er al een DoubleArray bestaat dan maakt hij deze niet meer aan. MAW er wordt maar een keer gealloceert, althans dat moet aangezien dat afgedwonen wirdt door de manier van registeren van het object.
Wat de TS dus moet doen is niet Activator.GetObject gebruiken, maar een service definieren die een GetDouble() method heeft, en DIE method returned de static instance in de singleton.
dat doe ik hier toch? mijn double array is het remote object die welke GetDouble() implementeerd

U can call me sir.... or justice as long as u bow down ;)


Acties:
  • 0 Henk 'm!

  • justice strike
  • Registratie: Juni 2001
  • Laatst online: 08-08 09:26
whoami schreef op vrijdag 24 oktober 2008 @ 09:45:
[...]
Idd.
Op de server bestaat er maar één instantie van DoubleArray, maar bij iedere call naar GetDouble() wordt er een nieuwe array gealloceerd.
hoezo wordt er een nieuwe array gealloceerd? ik return alleen een waarde in GetDouble.

U can call me sir.... or justice as long as u bow down ;)


Acties:
  • 0 Henk 'm!

  • EfBe
  • Registratie: Januari 2000
  • Niet online
justice strike schreef op vrijdag 24 oktober 2008 @ 10:49:
[...]

hoezo wordt er een nieuwe array gealloceerd? ik return alleen een waarde in GetDouble.
je creeert een nieuwe instance van GetDouble, elke keer dat de Activator wordt gebruikt, immers hij kan alleen een getDouble() callen wanneer hij een instance van die Double class heeft en DIE is juist server side.

MarshallByRefObject is niet een 'magische' class om thread safety te garanderen. Singleton creeeren is een delikaat onderwerp en Jon Skeet heeft daar de guide voor, dus gewoon doen wat Jon zegt: http://www.yoda.arachsys.com/csharp/singleton.html

(Dus iets in de trant van:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
[Serializable()]
public static class DoubleArraySingleton
{
    static byte[] _instance = new byte[160000000];
    
    static DoubleArraySingleton() {}
    
    static byte[] GetInstance()
    {
        return _instance;
    }
}


Dan maak je je service die een byte[] teruggeeft. Die service implementeert een interface (gedefinieerd in een aparte assembly, gereferenced door client EN service) met de method GetDouble(). Die interface gebruik je op de client om de service te accessen, De service class inherit van MarshallByRefObject.

In de GetDouble() method van de service doe je:
C#:
1
2
3
4
public byte[] GetDouble()
{
    return DoubleArraySingleton.GetInstance();
}


Alleen dan kun je de data transfer testen, want je DoubleArray moet over het lijntje by value. Dus je gebruikt je service in je client ong zoals dit:
code:
1
2
3
4
5
6
7
8
9
TcpChannel channel = new TcpChannel();
ChannelServices.RegisterChannel(channel, true);

MarshalByRefObject o = (MarshalByRefObject)RemotingServices.Connect(typeof(IService), string.Format("tcp://{0}:65100/theEndPoint", SERVERNAME));
IService service = o as IService;
if(service == null)
{
    throw new Exception("Service couldn't be obtained. Aborting");
}

Na deze code kun je, wanneer IService je service interface is, dus service.GetDouble() doen om de data te obtainen.

Het moet me van het hart dat de eigenwijsheid in deze thread je wel in de weg heeft gestaan om het op te lossen. Als je remoting wilt testen moet je een sevice instance aanmaken en zijn methods aanroepen, niet via de manier waarop jij het hebt geprobeerd.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 01:56
EfBe schreef op vrijdag 24 oktober 2008 @ 11:51:
[...]

je creeert een nieuwe instance van GetDouble, elke keer dat de Activator wordt gebruikt, immers hij kan alleen een getDouble() callen wanneer hij een instance van die Double class heeft en DIE is juist server side.

MarshallByRefObject is niet een 'magische' class om thread safety te garanderen. Singleton creeeren is een delikaat onderwerp en Jon Skeet heeft daar de guide voor, dus gewoon doen wat Jon zegt: http://www.yoda.arachsys.com/csharp/singleton.html
Hmm .... Ik weet niet in hoeverre je bekend bent met remoting, maar een 'remoting singleton' en een 'singleton' kan je niet 'zomaar' vergelijken.

Bij .NET remoting garandeert de runtime dat, indien je een remote server activated object als 'singleton' specifieert, dat hij dan maar één instantie maakt van dit object.
You use the WellKnownObjectMode enumeration to configure server-activated objects as Singleton or SingleCall objects. Singleton objects are objects for which there will always be only one instance, regardless of how many clients there are for that object, and which have a default lifetime. (The client can use the lifetime lease system to participate in the lifetime of Singleton instances. For details, see Lifetime Leases.) When you configure an object to be a SingleCall object, the system creates a new object for each client method invocation. Because a client will get a reference to a new instance on each invocation, SingleCall types do not participate in the lifetime lease system.
afaik, hoef je je als ontwikkelaar van je remote instance, zelf geen rekening te houden met het feit of er nu al een instance is of niet.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Dat is bij mij toch ook zo: de service. Probeer maar wat ik geschetst heb, want wat hij doet werkt iig niet.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Acties:
  • 0 Henk 'm!

  • justice strike
  • Registratie: Juni 2001
  • Laatst online: 08-08 09:26
Volgens mij halen we nu 2 concepten door elkaar.

Je hebt services en remote objects. Wat ik probeer te doen is een remote object te gebruiken. Services wil ik dus niet gebruiken omdat ze te gelimiteerd zijn.

Overigens heb ik al geprobeerd om te connecten zoals jij zei nl. met:

code:
1
MarshalByRefObject o = (MarshalByRefObject)RemotingServices.Connect(typeof(IService), string.Format("tcp://{0}:65100/theEndPoint", SERVERNAME));


maakt niets uit. Geheugengebruik neemt ook toe en je moet dan ook nog eens je service disconnecten (en dus bij gaan houden of je dat wel gedaan hebt). Is dus eigenlijk onhandig.

//edit het moet overigens ook geen static class zijn. en ik moet whoamy nu wel gelijk geven hierop, de remoting library moet ervoor zorgen dat deze classe niet meerdere keren aangemaakt wordt. Ik ga zo even een printstatement maken. Dan kunnen we in iedergeval uitsluiten dat het meerdere keren aangemaakt wordt.

ok. Net een printstatement in de constructor gezet. De classe is door remoting ook daadwerkelijk omgetoverd tot een singleton. dwz de constructor wordt maar 1 keer aangeroepen en er wordt dus maar 1 keer geheugen gereserveerd voor de array. Er meot dus iets anders aan de hand zijn.

overigens is er een hele logische reden waarom je dit bij remoting singletons anders moet oplossen. Het is voor een instantie namelijk moeilijk na te gaan of hij de enige is in een remoting environment.

[ Voor 88% gewijzigd door justice strike op 24-10-2008 13:41 ]

U can call me sir.... or justice as long as u bow down ;)


Acties:
  • 0 Henk 'm!

  • justice strike
  • Registratie: Juni 2001
  • Laatst online: 08-08 09:26
voor wie het wil weten. Er schijnt een bug te zitten in de binary serilization class welke ervoor zorgt dat grote hoeveelheden data niet verstuurd kunnen worden. Tevens reserveerd de serilization class een stuk geheugen ter grote van het te versturen data. Wil je dus meerdere connections tegelijk serven krijg je dus een toename in geheugengebruik. bij 160 mb per connectie neemt dat erg snel toe. Oplossing was dus om het in kleinere brokken te splitsen (10 mb per stuk) de connectie snelheid gaat wel omlaag, maar de geheugen problemen zijn er niet meer.

de bug in de serilization heeft er mee te maken dat er een heap gebruikt wordt. Als je een connectie maakt dan wordt er geheugen gereserveerd op de heap. Als er nog een connectie gemaakt wordt (in mijn geval) wordt er nog meer geheugen gereserveerd bovenop de al gereserveerde blokken. Als de eerste connectie dan klaar is wordt het geheugen niet vrij gegeven totdat de connectie die erna is aangemaakt ook klaar is. Als je dus vaak meerdere connecties gebruikt kan dat dus aardig vast lopen.

[ Voor 30% gewijzigd door justice strike op 27-10-2008 01:25 ]

U can call me sir.... or justice as long as u bow down ;)

Pagina: 1